Ticket #22664: flexibilize-presets_v7.patch

File flexibilize-presets_v7.patch, 75.0 KB (added by anonymous, 2 years ago)
  • resources/data/tagging-preset.xsd

     
    100100    <complexType name="group">
    101101        <annotation>
    102102            <documentation>
    103                 Used to group items in sub menus. name is required, icon is optional attribute.
     103                Used to group items in sub menus. name is required, icon and item_sort are optional attributes.
    104104            </documentation>
    105105        </annotation>
    106106        <complexContent>
    107107            <extension base="tns:group-parent">
    108108                <attributeGroup ref="tns:attributes.name" />
     109                <attribute name="items_sort" type="tns:items_sort" />
    109110            </extension>
    110111        </complexContent>
    111112    </complexType>
     
    198199                    <group ref="tns:optional_elements" />
    199200                    <element name="key" type="tns:key" />
    200201                    <element name="optional" type="tns:optional" minOccurs="0" />
     202                    <element name="selectgroup" type="tns:selectgroup" minOccurs="0" />
    201203                    <element name="roles" type="tns:roles" minOccurs="0" />
    202204                </choice>
    203205            </sequence>
     
    267269                ]]></documentation>
    268270            </annotation>
    269271        </attribute>
     272        <attribute name="prefix" type="string">
     273                <annotation>
     274                    <documentation>
     275                        Text that will be put at the start of the resulting value if key is empty, it's not used for appending of existing values.
     276                    </documentation>
     277                </annotation>
     278        </attribute>
     279        <attributeGroup ref="tns:attributes.append" />
    270280        <attribute name="match" type="tns:match" />
    271281    </complexType>
    272282
     
    378388            </annotation>
    379389        </attribute>
    380390        <attributeGroup ref="tns:attributes.icon" />
     391        <attribute name="delimiter" type="tns:values.delimiter" />
    381392        <anyAttribute processContents="skip" />
    382393    </complexType>
    383394
     
    404415        <attributeGroup ref="tns:attributes.icon" />
    405416        <attributeGroup ref="tns:attributes.values" />
    406417        <attribute name="use_last_as_default" type="tns:last_default" />
     418        <attribute name="if_needed_only" type="tns:if_needed_only" />
    407419        <attribute name="editable" type="boolean">
    408420            <annotation>
    409421                <documentation>
     
    425437    <complexType name="multiselect">
    426438        <!-- use either list_entry's or a combination of values/display_values -->
    427439        <sequence>
     440            <element name="selectgroup" type="tns:selectgroup" minOccurs="0" maxOccurs="unbounded" />
    428441            <group ref="tns:list_elements" minOccurs="0" maxOccurs="unbounded" />
    429442        </sequence>
    430443        <attributeGroup ref="tns:attributes.key" />
     
    433446        <attributeGroup ref="tns:attributes.values" />
    434447        <attribute name="use_last_as_default" type="tns:last_default" />
    435448        <attribute name="match" type="tns:match" />
    436 
     449                <attribute name="quick_select" type="boolean">
     450                        <annotation>
     451                    <documentation>
     452                        Allows to enable quick selection of list entries with just clicking on it, without the need to use keyboard. Default is false.
     453                    </documentation>
     454                </annotation>
     455                </attribute>       
     456        <attribute name="prefix" type="string">
     457                <annotation>
     458                    <documentation>
     459                        Text that will be put at the start of the resulting value. If values start with prefix, it will be remove from the value first.
     460                    </documentation>
     461                </annotation>
     462        </attribute>
     463               
    437464        <attribute name="type" use="prohibited" />
    438465        <attribute name="value" use="prohibited" />
    439466        <attribute name="name" use="prohibited" />
     
    441468        <attribute name="display-values" use="prohibited" />
    442469        <anyAttribute processContents="skip" />
    443470    </complexType>
    444 
     471   
    445472    <complexType name="checkgroup">
    446473        <annotation>
    447474            <documentation>
     
    462489        </attribute>
    463490        <anyAttribute processContents="skip" />
    464491    </complexType>
     492   
     493    <complexType name="selectgroup">
     494        <annotation>
     495            <documentation>
     496                To group list_entries for multiselect. From all list_entries in a group only one can be selected at a time.
     497            </documentation>
     498        </annotation>
     499        <sequence>
     500            <choice minOccurs="1" maxOccurs="unbounded">
     501                <element name="list_entry" type="tns:list_entry" />
     502                <element name="reference" type="tns:reference" />
     503            </choice>
     504        </sequence>
     505        <attribute name="exclusive" type="boolean">
     506            <annotation>
     507                <documentation><![CDATA[
     508                    If items of the <selectgroup> can only be selected when no other item in any other <selectgroup> is selected.
     509                ]]></documentation>
     510            </annotation>
     511        </attribute>
     512        <anyAttribute processContents="skip" />
     513    </complexType>
    465514
    466515    <complexType name="check">
    467516        <attributeGroup ref="tns:attributes.key" />
     
    502551            <enumeration value="off" />
    503552        </restriction>
    504553    </simpleType>
     554   
     555    <simpleType name="append">
     556        <annotation>
     557            <documentation>
     558                Specify if value should be appended to existing value. This defaults implicitly to default if append_value is provided.
     559            </documentation>
     560        </annotation>
     561        <restriction base="string">
     562            <enumeration value="default" />
     563            <enumeration value="always" />
     564        </restriction>
     565    </simpleType>
     566   
     567    <simpleType name="items_sort">
     568        <annotation>
     569            <documentation>
     570                If the items in the menu should be sorted. Defaults to "yes", when "always" is set the menu items will be sorted regardless how the sorting is configured in JOSM.
     571            </documentation>
     572        </annotation>
     573        <restriction base="string">
     574            <enumeration value="yes" />
     575            <enumeration value="no" />
     576            <enumeration value="always" />
     577        </restriction>
     578    </simpleType>
     579       
     580    <simpleType name="values.delimiter">
     581                 <annotation>
     582                <documentation><![CDATA[
     583                    The character that separates values. In case of <combo /> the default is comma. In case of <multiselect /> the default is semicolon and this will also be used to separate selected values in the tag.
     584                ]]></documentation>
     585          </annotation>
     586          <restriction base="string">
     587                <minLength value="1"/>
     588                <maxLength value="1"/>
     589          </restriction>
     590    </simpleType>
     591   
     592    <simpleType name="append.delimiter">
     593                 <annotation>
     594                <documentation><![CDATA[
     595                    The character that separates values for <key />. The default is semicolon and it's possible to provide an empty delimiter.
     596                ]]></documentation>
     597          </annotation>
     598          <restriction base="string">
     599                <minLength value="0"/>
     600                <maxLength value="1"/>
     601          </restriction>
     602    </simpleType>
     603   
     604    <simpleType name="if_needed_only">
     605        <annotation>
     606            <documentation>
     607                Show combo selection only if key is missing otherwise don't show it and retain current value.
     608            </documentation>
     609        </annotation>
     610        <restriction base="string">
     611            <enumeration value="true" />
     612            <enumeration value="false" />
     613        </restriction>
     614    </simpleType>
    505615
    506616    <simpleType name="last_default">
    507617        <annotation>
     
    588698            <enumeration value="optional" />
    589699        </restriction>
    590700    </simpleType>
     701   
     702    <simpleType name="sort_options">
     703        <annotation>
     704            <documentation>
     705                Possible options for values_sort. Default is "true";
     706            </documentation>
     707        </annotation>
     708        <restriction base="string">
     709            <enumeration value="true" />
     710            <enumeration value="false" />
     711            <enumeration value="user" />
     712        </restriction>
     713    </simpleType>
    591714
    592715    <!-- Types and documentation for attributes -->
    593716
     717    <attributeGroup name="attributes.append">
     718        <attribute name="append_value" type="string">
     719            <annotation>
     720                <documentation><![CDATA[
     721                    Specify a value to be appended to the <key> tag. Optional if this value should be used instead of value. The value is only appened if it doesn't already is set for <key> tag or if append=always was specified.
     722                ]]></documentation>
     723            </annotation>
     724        </attribute>
     725        <attribute name="append" type="tns:append" />
     726        <attribute name="delimiter" type="tns:append.delimiter" />
     727    </attributeGroup>
     728
    594729    <attributeGroup name="attributes.name">
    595730        <attribute name="name" type="string" use="required">
    596731            <annotation>
     
    671806                </documentation>
    672807            </annotation>
    673808        </attribute>
    674         <attribute name="values_sort" type="boolean">
     809        <attribute name="values_sort" type="tns:sort_options">
    675810            <annotation>
    676811                <documentation>
    677812                    Values of are sorted alphabetic in every language. With this attribute you can disable the alphabetic sorting if the values should keep the given order, see #5509 and #11926. (In the JOSM internal preset this is used e.g. for the keys tracktype, direction, network, smoothness, visibility or trail_visibility.) Default is "true".<br />
     
    693828                </documentation>
    694829            </annotation>
    695830        </attribute>
    696         <attribute name="delimiter" type="string">
    697             <annotation>
    698                 <documentation><![CDATA[
    699                     The character that separates values. In case of <combo /> the default is comma. In case of <multiselect /> the default is semicolon and this will also be used to separate selected values in the tag.
    700                 ]]></documentation>
    701             </annotation>
    702         </attribute>
     831        <attribute name="delimiter" type="tns:values.delimiter" />
    703832    </attributeGroup>
    704833
    705834    <attributeGroup name="attributes.icon">
  • src/org/openstreetmap/josm/gui/dialogs/properties/PresetListPanel.java

     
    3939            Collection<OsmPrimitive> selection = t.createSelection(presetHandler.getSelection());
    4040            if (selection.isEmpty())
    4141                return;
    42             int answer = t.showDialog(selection, false);
     42            int answer = t.showDialog(selection, false, (e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == MouseEvent.CTRL_DOWN_MASK);
    4343            DataSet ds = selection.iterator().next().getDataSet();
    4444            boolean locked = ds != null && ds.isLocked();
    4545
  • src/org/openstreetmap/josm/gui/preferences/map/TaggingPresetPreference.java

     
    154154    private SourceEditor sources;
    155155    private JCheckBox useValidator;
    156156    private JCheckBox sortMenu;
     157    private JCheckBox ifNeddedOnlyEnabled;
    157158
    158159    /**
    159160     * Registers a new additional preset source provider.
     
    172173    public void addGui(PreferenceTabbedPane gui) {
    173174        useValidator = new JCheckBox(tr("Run data validator on user input"), TaggingPreset.USE_VALIDATOR.get());
    174175        sortMenu = new JCheckBox(tr("Sort presets menu alphabetically"), TaggingPresets.SORT_MENU.get());
    175 
     176        ifNeddedOnlyEnabled = new JCheckBox(tr("Show input dialogs only if needed (can be overwritten with CTRL key down)"), TaggingPresets.IF_NEEDED_ONLY_ENABLED.get());
    176177        final JPanel panel = new JPanel(new GridBagLayout());
    177178        panel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
    178179
    179180        panel.add(useValidator, GBC.std().insets(5, 5, 0, 0));
    180181        panel.add(new JLabel(ImageProvider.get("dialogs/validator")), GBC.eol().insets(5, 5, 0, 0));
    181182        panel.add(sortMenu, GBC.eol().insets(5, 0, 5, 0));
     183        panel.add(ifNeddedOnlyEnabled, GBC.eol().insets(5, 0, 5, 0));
    182184
    183185        sources = new TaggingPresetSourceEditor();
    184186        panel.add(sources, GBC.eol().fill(GBC.BOTH));
     
    252254    @Override
    253255    public boolean ok() {
    254256        TaggingPreset.USE_VALIDATOR.put(useValidator.isSelected());
    255         if (sources.finish() || TaggingPresets.SORT_MENU.put(sortMenu.isSelected())) {
     257        boolean rebuild = TaggingPresets.SORT_MENU.put(sortMenu.isSelected());
     258        rebuild = TaggingPresets.IF_NEEDED_ONLY_ENABLED.put(ifNeddedOnlyEnabled.isSelected()) || rebuild;
     259
     260        if (sources.finish() || rebuild) {
    256261            TaggingPresets.destroy();
    257262            TaggingPresets.initialize();
    258263        }
  • src/org/openstreetmap/josm/gui/tagging/presets/TaggingPreset.java

     
    138138    public boolean preset_name_label;
    139139
    140140    /**
     141     * If menu items should be sorted
     142     */
     143    public String items_sort = "yes";
     144
     145    /**
    141146     * The types as preparsed collection.
    142147     */
    143148    public transient Set<TaggingPresetType> types;
     
    255260    }
    256261
    257262    /**
     263     * Called from the XML parser to set the sort option.
     264     * @param sort The sort value for the menu items.
     265     * @since 18619
     266     */
     267    public void setItems_sort(final String sort) {
     268        this.items_sort = sort;
     269    }
     270
     271    /**
    258272     * Called from the XML parser to set the icon.
    259273     * The loading task is performed in the background in order to speedup startup.
    260274     * @param iconName icon name
     
    362376     * This includes the elements from the individual {@link TaggingPresetItem items}.
    363377     *
    364378     * @param selected the selected primitives
     379     * @param ctrlDown if the CTRL key was pressed while selecting preset menu entry
    365380     * @return the newly created panel
    366381     */
    367     public PresetPanel createPanel(Collection<OsmPrimitive> selected) {
     382    public PresetPanel createPanel(Collection<OsmPrimitive> selected, boolean ctrlDown) {
    368383        PresetPanel p = new PresetPanel();
    369384
    370385        final JPanel pp = new JPanel();
     
    422437        TaggingPresetItem previous = null;
    423438        for (TaggingPresetItem i : data) {
    424439            if (i instanceof Link) {
    425                 i.addToPanel(linkPanel, itemGuiSupport);
     440                i.addToPanel(linkPanel, itemGuiSupport, ctrlDown);
    426441                p.hasElements = true;
    427442            } else {
    428443                if (i instanceof PresetLink) {
     
    431446                        itemPanel.add(link.createLabel(), GBC.eol().insets(0, 8, 0, 0));
    432447                    }
    433448                }
    434                 if (i.addToPanel(itemPanel, itemGuiSupport)) {
     449                if (i.addToPanel(itemPanel, itemGuiSupport, ctrlDown)) {
    435450                    p.hasElements = true;
    436451                }
    437452            }
     
    503518        if (ds == null) {
    504519            return;
    505520        }
    506         showAndApply(ds.getSelected());
     521        showAndApply(ds.getSelected(), (e.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK);
    507522    }
    508523
    509524    /**
    510525     * {@linkplain #showDialog Show preset dialog}, apply changes
    511526     * @param primitives the primitives
     527     * @param ctrlDown if the CTRL key was pressed while selecting preset menu entry
    512528     */
    513     public void showAndApply(Collection<OsmPrimitive> primitives) {
     529    public void showAndApply(Collection<OsmPrimitive> primitives, boolean ctrlDown) {
    514530        // Display dialog even if no data layer (used by preset-tagging-tester plugin)
    515531        Collection<OsmPrimitive> sel = createSelection(primitives);
    516         int answer = showDialog(sel, supportsRelation());
     532        int answer = showDialog(sel, supportsRelation(), ctrlDown);
    517533
    518534        if (!sel.isEmpty() && answer == DIALOG_ANSWER_APPLY) {
    519535            Command cmd = createCommand(sel, getChangedTags());
     
    598614     * Shows the preset dialog.
    599615     * @param sel selection
    600616     * @param showNewRelation whether to display "New relation" button
     617     * @param ctrlDown if the CTRL key was pressed while selecting preset menu entry
    601618     * @return the user choice after the dialog has been closed
    602619     */
    603     public int showDialog(Collection<OsmPrimitive> sel, boolean showNewRelation) {
    604         PresetPanel p = createPanel(sel);
     620    public int showDialog(Collection<OsmPrimitive> sel, boolean showNewRelation, boolean ctrlDown) {
     621        PresetPanel p = createPanel(sel, ctrlDown);
    605622
    606623        int answer = 1;
    607624        boolean canCreateRelation = types == null || types.contains(TaggingPresetType.RELATION);
  • src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetItem.java

     
    7878     * All components defining this tagging preset item must be added to given panel.
    7979     *
    8080     * @param p The panel where components must be added
     81     * @param ctrlDown if the CTRL key was pressed when selecting preset menu item
    8182     * @param support supporting class for creating the GUI
    8283     * @return {@code true} if this item adds semantic tagging elements, {@code false} otherwise.
    8384     */
    84     protected abstract boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support);
     85    protected abstract boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support, boolean ctrlDown);
    8586
    8687    /**
    8788     * Adds the new tags to apply to selected OSM primitives when the preset holding this item is applied.
  • src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetMenu.java

     
    120120     * Sorts the menu items using the translated item text
    121121     */
    122122    public void sortMenu() {
    123         TaggingPresetMenu.sortMenu(this.menu);
     123        TaggingPresetMenu.sortMenu(this.menu, TaggingPresets.SORT_MENU.get());
    124124    }
    125125
    126126    /**
    127127     * Sorts the menu items using the translated item text
    128128     * @param menu menu to sort
     129     * @param itemssort if menu should be sorted.
    129130     */
    130     public static void sortMenu(JMenu menu) {
     131    public static void sortMenu(JMenu menu, boolean itemssort) {
     132        Action a = menu.getAction();
     133
     134        boolean sort = itemssort;
     135
     136        if (a instanceof TaggingPreset) {
     137            sort = (sort && ((TaggingPreset) a).items_sort.equals("yes")) || ((TaggingPreset) a).items_sort.equals("always");
     138        }
     139
    131140        Component[] items = menu.getMenuComponents();
    132141        PresetTextComparator comp = new PresetTextComparator();
    133142        List<JMenuItem> sortarray = new ArrayList<>();
     
    135144        for (int i = 0; i < items.length; i++) {
    136145            Object item = items[i];
    137146            if (item instanceof JMenu) {
    138                 sortMenu((JMenu) item);
     147                sortMenu((JMenu) item, itemssort);
    139148            }
    140             if (item instanceof JMenuItem) {
    141                 sortarray.add((JMenuItem) item);
    142                 if (i == items.length-1) {
     149            if (sort) {
     150                if (item instanceof JMenuItem) {
     151                    sortarray.add((JMenuItem) item);
     152                    if (i == items.length-1) {
     153                        handleMenuItem(menu, comp, sortarray, lastSeparator);
     154                        sortarray = new ArrayList<>();
     155                        lastSeparator = 0;
     156                    }
     157                } else if (item instanceof JSeparator) {
    143158                    handleMenuItem(menu, comp, sortarray, lastSeparator);
    144159                    sortarray = new ArrayList<>();
    145                     lastSeparator = 0;
     160                    lastSeparator = i;
    146161                }
    147             } else if (item instanceof JSeparator) {
    148                 handleMenuItem(menu, comp, sortarray, lastSeparator);
    149                 sortarray = new ArrayList<>();
    150                 lastSeparator = i;
    151162            }
    152163        }
    153164    }
  • src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetReader.java

     
    3939import org.openstreetmap.josm.gui.tagging.presets.items.PresetListEntry;
    4040import org.openstreetmap.josm.gui.tagging.presets.items.Roles;
    4141import org.openstreetmap.josm.gui.tagging.presets.items.Roles.Role;
     42import org.openstreetmap.josm.gui.tagging.presets.items.SelectGroup;
    4243import org.openstreetmap.josm.gui.tagging.presets.items.Space;
    4344import org.openstreetmap.josm.gui.tagging.presets.items.Text;
    4445import org.openstreetmap.josm.io.CachedFile;
     
    145146        parser.mapOnStart("roles", Roles.class);
    146147        parser.map("role", Role.class);
    147148        parser.mapBoth("checkgroup", CheckGroup.class);
     149        parser.mapBoth("selectgroup", SelectGroup.class);
    148150        parser.map("check", Check.class);
    149151        parser.map("combo", Combo.class);
    150152        parser.map("multiselect", MultiSelect.class);
     
    182184
    183185        /** to detect end of {@code <checkgroup>} */
    184186        CheckGroup lastcheckgroup = null;
     187        /** to detect end of {@code <selectgroup>} */
     188        SelectGroup lastselectgroup = null;
     189        int selectgroupcount = PresetListEntry.SELECT_GROUP_NONE;
    185190        /** to detect end of {@code <group>} */
    186191        TaggingPresetMenu lastmenu = null;
    187192        /** to detect end of reused {@code <group>} */
     
    302307                            all.getLast().data.add((TaggingPresetItem) o);
    303308                        }
    304309                    } else if (o instanceof PresetListEntry) {
    305                         listEntries.add((PresetListEntry) o);
     310                        PresetListEntry entry = (PresetListEntry) o;
     311
     312                        if(lastselectgroup != null) {
     313                            if(!lastselectgroup.exclusive) {
     314                                entry.select_group = selectgroupcount;
     315                            }
     316                            else {
     317                                entry.select_group = -selectgroupcount;
     318                            }
     319                        }
     320
     321                        listEntries.add(entry);
    306322                    } else if (o instanceof CheckGroup) {
    307323                        CheckGroup cg = (CheckGroup) o;
    308324                        if (cg == lastcheckgroup) {
     
    316332                        } else {
    317333                            lastcheckgroup = cg;
    318334                        }
     335                    } else if (o instanceof SelectGroup) {
     336                        SelectGroup sg = (SelectGroup) o;
     337                        if (sg == lastselectgroup) {
     338                            lastselectgroup = null;
     339                        } else {
     340                            lastselectgroup = sg;
     341                            selectgroupcount++;
     342                        }
    319343                    } else {
    320344                        if (!checks.isEmpty()) {
    321345                            all.getLast().data.addAll(checks);
     
    329353                        }
    330354                        listEntries.clear();
    331355                        lastrole = null;
     356                        selectgroupcount = PresetListEntry.SELECT_GROUP_NONE;
    332357                    }
    333358                } else
    334359                    throw new SAXException(tr("Preset sub element without parent"));
  • src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresets.java

     
    5454     */
    5555    public static final BooleanProperty SORT_MENU = new BooleanProperty("taggingpreset.sortvalues", true);
    5656    /**
     57     * Sort presets menu alphabetically
     58     */
     59    public static final BooleanProperty IF_NEEDED_ONLY_ENABLED = new BooleanProperty("taggingpreset.ifneededonlyenabled", false);
     60    /**
    5761     * Custom icon sources
    5862     */
    5963    public static final ListProperty ICON_SOURCES = new ListProperty("taggingpreset.icon.sources", null);
     
    123127                }
    124128            }
    125129        }
    126         if (SORT_MENU.get()) {
    127             TaggingPresetMenu.sortMenu(presetsMenu);
    128         }
     130
     131        TaggingPresetMenu.sortMenu(presetsMenu, SORT_MENU.get());
     132
    129133        listeners.forEach(TaggingPresetListener::taggingPresetsModified);
    130134    }
    131135
  • src/org/openstreetmap/josm/gui/tagging/presets/items/Check.java

     
    3535    private Boolean def;
    3636
    3737    @Override
    38     public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support) {
     38    public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support, boolean ctrlDown) {
    3939
    4040        // find out if our key is already used in the selection.
    4141        final Usage usage = determineBooleanUsage(support.getSelected(), key);
  • src/org/openstreetmap/josm/gui/tagging/presets/items/CheckGroup.java

     
    3131    public final List<Check> checks = new LinkedList<>();
    3232
    3333    @Override
    34     public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support) {
     34    public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support, boolean ctrlDown) {
    3535        int rows = (int) Math.ceil(checks.size() / ((double) columns));
    3636        JPanel panel = new JPanel(new GridLayout(rows, columns));
    3737
    3838        int i = 0;
    3939        for (Check check : checks) {
    40             check.addToPanel(panel, support);
     40            check.addToPanel(panel, support, ctrlDown);
    4141            i++;
    4242        }
    4343        for (; i < rows * columns; i++) {
  • src/org/openstreetmap/josm/gui/tagging/presets/items/Combo.java

     
    8484    }
    8585
    8686    @Override
    87     protected boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support) {
     87    protected boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support, boolean ctrlDown) {
    8888        initializeLocaleText(null);
    8989        usage = determineTextUsage(support.getSelected(), key);
    9090        seenValues.clear();
     
    168168        combobox.setToolTipText(getKeyTooltipText());
    169169        combobox.applyComponentOrientation(OrientationAction.getValueOrientation(key));
    170170
    171         return true;
     171
     172        return ctrlDown || isNeeded(usage);
    172173    }
    173174
     175
     176
    174177    /**
    175178     * Finds the PresetListEntry that matches value.
    176179     * <p>
  • src/org/openstreetmap/josm/gui/tagging/presets/items/ComboMultiSelect.java

     
    3535 * Abstract superclass for combo box and multi-select list types.
    3636 */
    3737public abstract class ComboMultiSelect extends KeyedItem {
    38 
     38    protected static final String VALUE_SORT_USER = "user";
    3939    /**
    4040     * A list of entries.
    4141     * The list has to be separated by commas (for the {@link Combo} box) or by the specified delimiter (for the {@link MultiSelect}).
     
    5353    /** Disabled internationalisation for value to avoid mistakes, see #11696 */
    5454    public boolean values_no_i18n; // NOSONAR
    5555    /** Whether to sort the values, defaults to true. */
    56     public boolean values_sort = true; // NOSONAR
     56    public String values_sort = String.valueOf(true); // NOSONAR
     57    /** Whether to show this combo in dialog only when it's needed.
     58     * It's needed when key doesn't exist or if current value is not in values */
     59    public boolean if_needed_only = false; // NOSONAR
    5760    /**
    5861     * A list of entries that is displayed to the user.
    5962     * Must be the same number and order of entries as {@link #values} and editable must be false or not specified.
     
    138141                // editor-ersatz of a readonly combobox. fixes #6157
    139142                l.setText(value.getListDisplay(width));
    140143            }
     144
    141145            if (value.getCount() > 0) {
    142146                l.setFont(l.getFont().deriveFont(Font.ITALIC + Font.BOLD));
    143147            }
     
    310314            addListEntry(e);
    311315        }
    312316
    313         if (values_sort && TaggingPresets.SORT_MENU.get()) {
     317        if (values_sort.equals(String.valueOf(true)) && TaggingPresets.SORT_MENU.get()) {
    314318            Collections.sort(presetListEntries, (a, b) -> AlphanumComparator.getInstance().compare(a.getDisplayValue(), b.getDisplayValue()));
    315319        }
    316320    }
     
    430434    public MatchType getDefaultMatch() {
    431435        return MatchType.NONE;
    432436    }
     437
     438    protected final boolean isNeeded(Usage usage) {
     439        boolean result = !TaggingPresets.IF_NEEDED_ONLY_ENABLED.get() || !if_needed_only || usage.unused();
     440
     441        if (!result) {
     442            for (String v : usage.map.keySet()) {
     443                boolean found = false;
     444
     445                for (PresetListEntry p : presetListEntries) {
     446                    if (p.value.equals(v)) {
     447                        found = true;
     448                        break;
     449                    }
     450                }
     451
     452                if (!found) {
     453                    return true;
     454                }
     455            }
     456        }
     457
     458        return result;
     459    }
    433460}
  • src/org/openstreetmap/josm/gui/tagging/presets/items/ItemSeparator.java

     
    1818public class ItemSeparator extends TaggingPresetItem {
    1919
    2020    @Override
    21     public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support) {
     21    public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support, boolean ctrlDown) {
    2222        p.add(new JSeparator(), GBC.eol().fill(GBC.HORIZONTAL).insets(0, 5, 0, 5));
    2323        return false;
    2424    }
  • src/org/openstreetmap/josm/gui/tagging/presets/items/Key.java

     
    77
    88import javax.swing.JPanel;
    99
     10import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1011import org.openstreetmap.josm.data.osm.Tag;
    1112import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItemGuiSupport;
    1213
     
    1415 * Invisible type allowing to hardcode an OSM key/value from the preset definition.
    1516 */
    1617public class Key extends KeyedItem {
     18    private static final String VALUE_APPEND_ALWAYS = "always";
    1719
    1820    /** The hardcoded value for key */
    1921    public String value; // NOSONAR
    2022
     23    /** The hardcoded value for key appending existing value **/
     24    public String append_value;  // NOSONAR
     25
     26    /** The hardcoded delimiter to use for appending values **/
     27    public String delimiter = ";"; // NOSONAR
     28
     29    /** The hardcoded type of appending */
     30    public String append = null; // NOSONAR
     31
     32    /** The hardcoded prefix to use for setting value to empty key */
     33    public String prefix = null; // NOSONAR
     34
     35    private String useValue;
     36
    2137    @Override
    22     public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support) {
     38    public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support, boolean ctrlDown) {
     39        if (prefix != null) {
     40            useValue = prefix + value;
     41        }
     42        else {
     43            useValue = value;
     44        }
     45
     46        // If append_value is present append also if append was not set
     47        if (append_value != null || append != null) {
     48            String toUse = append_value != null ? append_value : value;
     49
     50            Collection<OsmPrimitive> col = support.getSelected();
     51
     52            for (OsmPrimitive pr : col) {
     53                String currentValue = pr.get(key);
     54
     55                if (currentValue != null) {
     56                    useValue = currentValue;
     57
     58                    if ((append != null && append.equals(VALUE_APPEND_ALWAYS)) || !useValue.contains(toUse)) {
     59                        useValue += delimiter + toUse;
     60                    }
     61
     62                    break;
     63                }
     64            }
     65        }
     66
    2367        return false;
    2468    }
    2569
     
    3377     * @return the tag
    3478     */
    3579    public Tag asTag() {
    36         return new Tag(key, value);
     80        return new Tag(key, useValue != null ? useValue : value);
    3781    }
    3882
    3983    @Override
     
    4387
    4488    @Override
    4589    public Collection<String> getValues() {
    46         return Collections.singleton(value);
     90        return Collections.singleton(useValue != null ? useValue : value);
    4791    }
    4892
    4993    @Override
    5094    public String toString() {
    51         return "Key [key=" + key + ", value=" + value + ", text=" + text
    52                 + ", text_context=" + text_context + ", match=" + match
    53                 + ']';
     95        return "Key [key=" + key + ", value=" + value + ", value_append=" + append_value
     96                + ", text=" + text + ", text_context=" + text_context + ", match=" + match
     97                + ", delimiter=" + delimiter + ']';
    5498    }
    5599}
  • src/org/openstreetmap/josm/gui/tagging/presets/items/Label.java

     
    1313public class Label extends TextItem {
    1414
    1515    @Override
    16     public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support) {
     16    public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support, boolean ctrlDown) {
    1717        initializeLocaleText(null);
    1818        JLabel label = new JLabel(locale_text);
    1919        addIcon(label);
  • src/org/openstreetmap/josm/gui/tagging/presets/items/Link.java

     
    3333    public String locale_href; // NOSONAR
    3434
    3535    @Override
    36     public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support) {
     36    public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support, boolean ctrlDown) {
    3737        initializeLocaleText(tr("More information about this feature"));
    3838        UrlLabel label = buildUrlLabel();
    3939        if (label != null) {
  • src/org/openstreetmap/josm/gui/tagging/presets/items/MultiSelect.java

     
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.gui.tagging.presets.items;
    33
     4import static org.openstreetmap.josm.tools.I18n.tr;
     5
    46import java.awt.Dimension;
     7import java.awt.GridBagLayout;
    58import java.awt.Insets;
    69import java.awt.Rectangle;
    7 import java.util.stream.Collectors;
     10import java.awt.event.MouseAdapter;
     11import java.awt.event.MouseEvent;
     12import java.util.Collections;
     13import java.util.List;
     14import java.util.Objects;
    815
    916import javax.swing.DefaultListModel;
     17import javax.swing.DefaultListSelectionModel;
     18import javax.swing.JButton;
    1019import javax.swing.JLabel;
    1120import javax.swing.JList;
    1221import javax.swing.JPanel;
    1322import javax.swing.JScrollPane;
     23import javax.swing.ListModel;
     24import javax.swing.ListSelectionModel;
     25import javax.swing.event.ListSelectionEvent;
     26import javax.swing.event.ListSelectionListener;
    1427
    1528import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItemGuiSupport;
     29import org.openstreetmap.josm.gui.util.ReorderableTableModel;
    1630import org.openstreetmap.josm.gui.widgets.OrientationAction;
    1731import org.openstreetmap.josm.tools.GBC;
     32import org.openstreetmap.josm.tools.ImageProvider;
     33import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
    1834
    1935/**
    2036 * Multi-select list type.
    2137 */
    2238public class MultiSelect extends ComboMultiSelect {
    23 
    2439    /**
    2540     * Number of rows to display (positive integer, optional).
    2641     */
    2742    public short rows; // NOSONAR
    2843
    2944    /** The model for the JList */
    30     protected final DefaultListModel<PresetListEntry> model = new DefaultListModel<>();
     45    protected final PresetListModel model = new PresetListModel();
    3146    /** The swing component */
    3247    protected final JList<PresetListEntry> list = new JList<>(model);
    3348
     49    /**
     50     * Text that will be put in front of the resulting value.
     51     */
     52    public String prefix; // NOSONAR
     53
     54    /**
     55     * If the entries in the list should be selected with clicking only.
     56     */
     57    public boolean quick_select = false;
     58
     59    /**
     60     * Use selection model that selects/deselects values with single click.
     61     * @since 18619
     62     */
     63    public MultiSelect() {
     64        list.setSelectionModel(new SingleClickSelectionModel(list));
     65    }
     66
    3467    private void addEntry(PresetListEntry entry) {
     68        addEntry(entry, -1);
     69    }
     70
     71    private void addEntry(PresetListEntry entry, int presetCount) {
     72        if (prefix != null && entry.value.startsWith(prefix)) {
     73            entry.value = entry.value.substring(prefix.length());
     74        }
     75
    3576        if (!seenValues.containsKey(entry.value)) {
    36             model.addElement(entry);
    37             seenValues.put(entry.value, entry);
     77            boolean add = true;
     78
     79            for (int i = 0; i < model.size(); i++) {
     80                PresetListEntry test = model.get(i);
     81
     82                if (test.delimiter != null && entry.value.matches(".+\\\\{0}" + test.delimiter+".+")) {
     83                    add = false;
     84
     85                    if (usage != null && usage.map.containsKey(entry.value)) {
     86                        usage.map.remove(entry.value);
     87                    }
     88
     89                    String[] parts = entry.value.split(test.delimiter,-1);
     90
     91                    for (int j = 0; j < parts.length; j++) {
     92                        if (prefix != null && parts[j].startsWith(prefix)) {
     93                            parts[j] = parts[j].substring(prefix.length());
     94                        }
     95                        addEntry(new PresetListEntry(parts[j], this, j == 0 ? String.valueOf(delimiter) : test.delimiter), presetCount);
     96                    }
     97
     98                    break;
     99                }
     100            }
     101
     102            if (add) {
     103                if (presetCount == -1) {
     104                    model.addElement(entry);
     105                }
     106                else {
     107                    model.insertElementAt(entry, model.getSize() - presetCount);
     108                }
     109                seenValues.put(entry.value, entry);
     110            }
    38111        }
    39112    }
    40113
     114    private void select(PresetListEntry entry, boolean addUsage) {
     115        for (int i = 0; i < model.getSize(); i++) {
     116            PresetListEntry test = model.get(i);
     117
     118            if (Objects.equals(test.value, entry.value)) {
     119                int[] indices = model.getSelectedIndices();
     120
     121                if (indices != null && indices.length > 0 && indices[indices.length - 1] > i) {
     122                    PresetListEntry removed = model.remove(i);
     123                    model.add(indices[indices.length-1], removed);
     124                    list.addSelectionInterval(indices[indices.length-1], indices[indices.length-1]);
     125                }
     126                else {
     127                    list.addSelectionInterval(i, i);
     128                }
     129
     130                if (addUsage && usage != null && usage.map != null && !usage.map.containsKey(test.value)) {
     131                    usage.map.put(test.value, 1);
     132                }
     133
     134                break;
     135            }
     136            else if (test.delimiter != null && entry.value.matches(".*\\\\{0}" + test.delimiter+".*")) {
     137                for (String part : entry.value.split(test.delimiter, -1)) {
     138                    select(new PresetListEntry(part, this, test.delimiter), true);
     139                }
     140            }
     141        }
     142    }
     143
    41144    @Override
    42     protected boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support) {
     145    protected boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support, boolean ctrlDown) {
    43146        initializeLocaleText(null);
    44147        usage = determineTextUsage(support.getSelected(), key);
     148
     149        if (prefix != null) {
     150            String[] keys = usage.map.keySet().toArray(new String[0]);
     151
     152            if(key != null) {
     153                for (String k : keys) {
     154                    if(k.startsWith(prefix)) {
     155                        Integer count = usage.map.remove(k);
     156                        usage.map.put(k.substring(prefix.length()), count);
     157                    }
     158                }
     159            }
     160        }
     161
    45162        seenValues.clear();
    46163        initListEntries();
    47 
    48164        model.clear();
    49165        // disable if the selected primitives have different values
    50166        list.setEnabled(usage.hasUniqueValue() || usage.unused());
     
    53169        // Add values from the preset.
    54170        presetListEntries.forEach(this::addEntry);
    55171
     172        int count = model.getSize();
     173
    56174        // Add all values used in the selected primitives. This also adds custom values and makes
    57175        // sure we won't lose them.
    58176        usage = usage.splitValues(String.valueOf(delimiter));
    59         for (String value: usage.map.keySet()) {
    60             addEntry(new PresetListEntry(value, this));
     177        String[] keys = usage.map.keySet().toArray(new String[0]);
     178
     179        if (keys != null) {
     180            for (String value: keys) {
     181                addEntry(new PresetListEntry(value, this), count);
     182            }
    61183        }
    62184
    63185        // Select the values in the initial value.
     
    65187            for (String value : initialValue.split(String.valueOf(delimiter), -1)) {
    66188                PresetListEntry e = new PresetListEntry(value, this);
    67189                addEntry(e);
    68                 int i = model.indexOf(e);
    69                 list.addSelectionInterval(i, i);
     190                select(e, !usage.unused());
    70191            }
    71192        }
     193        else if (default_ != null) {
     194            select(new PresetListEntry(default_, this), false);
     195        }
    72196
    73197        ComboMultiSelectListCellRenderer renderer = new ComboMultiSelectListCellRenderer(list, list.getCellRenderer(), 200, key);
    74198        list.setCellRenderer(renderer);
     
    89213                insets = sp.getInsets();
    90214                r.width += insets.left + insets.right;
    91215                r.height += insets.top + insets.bottom;
    92                 sp.setPreferredSize(new Dimension(r.width, r.height));
     216                sp.setPreferredSize(new Dimension(Math.max(r.width, sp.getPreferredSize().width), r.height));
    93217            }
    94218        }
    95         p.add(sp, GBC.eol().fill(GBC.HORIZONTAL)); // NOSONAR
     219
     220        if(values_sort.equals(VALUE_SORT_USER)) {
     221            final JButton up = new JButton(ImageProvider.get("dialogs", "up", ImageSizes.LARGEICON));
     222            up.setToolTipText(tr("Move the currently selected members up"));
     223            up.addActionListener(e -> {
     224                model.moveUp();
     225            });
     226            final JButton down = new JButton(ImageProvider.get("dialogs", "down", ImageSizes.LARGEICON));
     227            down.setToolTipText(tr("Move the currently selected members down"));
     228            down.addActionListener(e -> {
     229                model.moveDown();
     230            });
     231            up.setEnabled(model.canMoveUp());
     232            down.setEnabled(model.canMoveDown());
     233
     234            list.addListSelectionListener(new ListSelectionListener() {
     235                @Override
     236                public void valueChanged(ListSelectionEvent e) {
     237                    up.setEnabled(model.canMoveUp());
     238                    down.setEnabled(model.canMoveDown());
     239                }
     240            });
     241
     242            JPanel content = new JPanel(new GridBagLayout());
     243            content.add(sp, GBC.std(0,0).span(1, 4).fill());
     244            content.add(GBC.glue(0, 1), GBC.std(1, 0).fill(GBC.VERTICAL));
     245            content.add(up, GBC.std(1, 1));
     246            content.add(down, GBC.std(1, 2));
     247            content.add(GBC.glue(0, 1), GBC.std(1, 3).fill(GBC.VERTICAL));
     248
     249            p.add(content, GBC.eol().fill(GBC.HORIZONTAL)); // NOSONAR
     250        }
     251        else {
     252            p.add(sp, GBC.eol().fill(GBC.HORIZONTAL)); // NOSONAR
     253        }
    96254
    97255        list.addListSelectionListener(l -> support.fireItemValueModified(this, key, getSelectedItem().value));
    98256        list.setToolTipText(getKeyTooltipText());
    99257        list.applyComponentOrientation(OrientationAction.getValueOrientation(key));
    100258
    101         return true;
     259        return ctrlDown || isNeeded(usage);
    102260    }
    103261
    104262    @Override
    105263    protected PresetListEntry getSelectedItem() {
    106         return new PresetListEntry(list.getSelectedValuesList()
    107             .stream().map(e -> e.value).distinct().sorted().collect(Collectors.joining(String.valueOf(delimiter))), this);
     264         StringBuilder result = new StringBuilder();
     265         List<PresetListEntry> temp = list.getSelectedValuesList();
     266
     267         if (!temp.isEmpty()) {
     268             if (values_sort.equals(String.valueOf(true))) {
     269                 Collections.sort(temp);
     270             }
     271
     272             if (prefix != null) {
     273                 result.append(prefix);
     274             }
     275
     276             result.append(temp.get(0).value);
     277
     278             for (int i = 1; i < temp.size(); i++) {
     279                 if (result.indexOf(temp.get(i).value) == -1) {
     280                     result.append(temp.get(i).delimiter != null ? temp.get(i).delimiter : delimiter).append(temp.get(i).value);
     281                 }
     282             }
     283         }
     284
     285         return new PresetListEntry(result.toString(), this);
     286    }
     287
     288    private final class SingleClickSelectionModel extends DefaultListSelectionModel {
     289        private boolean mousePressed;
     290        private ListModel<PresetListEntry> model;
     291
     292        private SingleClickSelectionModel(JList<PresetListEntry> list) {
     293            this.model = list.getModel();
     294            list.addMouseListener(new MouseAdapter() {
     295                @Override
     296                public void mousePressed(MouseEvent e) {
     297                    mousePressed = true;
     298                }
     299                @Override
     300                public void mouseReleased(MouseEvent e) {
     301                    mousePressed = false;
     302                }
     303            });
     304        }
     305
     306        @Override
     307        public void addSelectionInterval(int index0, int index1) {
     308            removeSelectionForGroupAtIndex(index0);
     309            super.addSelectionInterval(index0, index1);
     310        }
     311
     312        private void removeSelectionForGroupAtIndex(int index) {
     313            if(!isSelectedIndex(index)) {
     314                int selectGroup = model.getElementAt(index).select_group;
     315
     316                for(int i = 0; i < model.getSize(); i++) {
     317                    if(isSelectedIndex(i) && (selectGroup < 0 || (model.getElementAt(i).select_group != PresetListEntry.SELECT_GROUP_NONE && model.getElementAt(i).select_group == selectGroup) || model.getElementAt(i).select_group < 0)) {
     318                        super.removeSelectionInterval(i, i);
     319                    }
     320                }
     321            }
     322        }
     323
     324        @Override
     325        public void setSelectionInterval(int index0, int index1) {
     326            if (quick_select && getSelectionMode() == MULTIPLE_INTERVAL_SELECTION) {
     327                if (!mousePressed) {
     328                    if (isSelectedIndex(index0)) {
     329                        super.removeSelectionInterval(index0, index1);
     330                    }
     331                    else {
     332                        removeSelectionForGroupAtIndex(index0);
     333                        super.addSelectionInterval(index0, index1);
     334                    }
     335                }
     336            }
     337            else {
     338                super.setSelectionInterval(index0, index1);
     339            }
     340        }
     341    }
     342
     343    private final class PresetListModel extends DefaultListModel<PresetListEntry> implements ReorderableTableModel<PresetListEntry> {
     344        @Override
     345        public PresetListEntry getValue(int index) {
     346            return get(index);
     347        }
     348
     349        @Override
     350        public PresetListEntry setValue(int index, PresetListEntry value) {
     351            return set(index, value);
     352        }
     353
     354        @Override
     355        public ListSelectionModel getSelectionModel() {
     356            return list.getSelectionModel();
     357        }
     358
     359        @Override
     360        public int getRowCount() {
     361            return size();
     362        }
    108363    }
    109364}
  • src/org/openstreetmap/josm/gui/tagging/presets/items/Optional.java

     
    1717
    1818    // TODO: Draw a box around optional stuff
    1919    @Override
    20     public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support) {
     20    public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support, boolean ctrlDown) {
    2121        initializeLocaleText(tr("Optional Attributes:"));
    2222        JLabel label = new JLabel(locale_text);
    2323        label.applyComponentOrientation(support.getDefaultComponentOrientation());
  • src/org/openstreetmap/josm/gui/tagging/presets/items/PresetLink.java

     
    3737
    3838        @Override
    3939        public void mouseClicked(MouseEvent e) {
    40             t.showAndApply(sel);
     40            t.showAndApply(sel, e.isControlDown());
    4141        }
    4242    }
    4343
     
    5454    }
    5555
    5656    @Override
    57     public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support) {
     57    public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support, boolean ctrlDown) {
    5858        final String presetName = preset_name;
    5959        Optional<TaggingPreset> found = TaggingPresets.getTaggingPresets().stream().filter(preset -> presetName.equals(preset.name)).findFirst();
    6060        if (found.isPresent()) {
  • src/org/openstreetmap/josm/gui/tagging/presets/items/PresetListEntry.java

     
    2121 * {@link MultiSelect}.
    2222 */
    2323public class PresetListEntry implements Comparable<PresetListEntry> {
     24    /** Value for entries without a select group*/
     25    public static final int SELECT_GROUP_NONE = 0;
    2426    /** Used to display an entry matching several different values. */
    2527    protected static final PresetListEntry ENTRY_DIFFERENT = new PresetListEntry(KeyedItem.DIFFERENT, null);
    2628    /** Used to display an empty entry used to clear values. */
     
    4648    public String locale_display_value; // NOSONAR
    4749    /** The localized version of {@link #short_description}. */
    4850    public String locale_short_description; // NOSONAR
     51    /** The delimiter for separating this entry from the previous */
     52    public String delimiter; // NOSONAR
     53    /** The select group for multi select */
     54    public int select_group = SELECT_GROUP_NONE;
    4955
    5056    private String cachedDisplayValue;
    5157    private String cachedShortDescription;
    5258    private ImageIcon cachedIcon;
    5359
     60
    5461    /**
    5562     * Constructs a new {@code PresetListEntry}, uninitialized.
    5663     *
     
    6774     * @param cms the ComboMultiSelect
    6875     */
    6976    public PresetListEntry(String value, ComboMultiSelect cms) {
     77        this(value, cms, null);
     78    }
     79
     80    /**
     81     * Constructs a new {@code PresetListEntry}, initialized with a value and
     82     * {@link ComboMultiSelect} context and the delimiter for this entry.
     83     *
     84     * @param value value
     85     * @param cms the ComboMultiSelect
     86     * @param delimiter The character to use to separate this entry from the previous
     87     * @since 18619
     88     */
     89    public PresetListEntry(String value, ComboMultiSelect cms, String delimiter) {
    7090        this.value = value;
    7191        this.cms = cms;
     92        this.delimiter = delimiter;
    7293    }
    7394
    7495    /**
  • src/org/openstreetmap/josm/gui/tagging/presets/items/Roles.java

     
    189189    public final List<Role> roles = new ArrayList<>(2);
    190190
    191191    @Override
    192     public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support) {
     192    public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support, boolean ctrlDown) {
    193193        p.add(new JLabel(" "), GBC.eol()); // space
    194194        if (!roles.isEmpty()) {
    195195            JPanel proles = new JPanel(new GridBagLayout());
  • src/org/openstreetmap/josm/gui/tagging/presets/items/SelectGroup.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.gui.tagging.presets.items;
     3
     4import java.util.List;
     5
     6import javax.swing.JPanel;
     7
     8import org.openstreetmap.josm.data.osm.Tag;
     9import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItem;
     10import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItemGuiSupport;
     11
     12/**
     13 * A group of {@link PresetListEntry}s.
     14 * @since 18637
     15 */
     16public class SelectGroup extends TaggingPresetItem {
     17    /** If items in this SelectGroup can only be selected when no item in the complete list is selected */
     18    public boolean exclusive = false;
     19
     20    @Override
     21    protected boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support, boolean ctrlDown) {
     22        // TODO Auto-generated method stub
     23        return false;
     24    }
     25
     26    @Override
     27    protected void addCommands(List<Tag> changedTags) {
     28        // TODO Auto-generated method stub
     29
     30    }
     31
     32}
  • src/org/openstreetmap/josm/gui/tagging/presets/items/Space.java

    Property changes on: src/org/openstreetmap/josm/gui/tagging/presets/items/SelectGroup.java
    ___________________________________________________________________
    Added: svn:mime-type
    ## -0,0 +1 ##
    +text/plain
     
    1717public class Space extends TaggingPresetItem {
    1818
    1919    @Override
    20     public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support) {
     20    public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support, boolean ctrlDown) {
    2121        p.add(new JLabel(" "), GBC.eol()); // space
    2222        return false;
    2323    }
  • src/org/openstreetmap/josm/gui/tagging/presets/items/Text.java

     
    7272    private transient TemplateEntry valueTemplate;
    7373
    7474    @Override
    75     public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support) {
     75    public boolean addToPanel(JPanel p, TaggingPresetItemGuiSupport support, boolean ctrlDown) {
    7676
    7777        AutoCompComboBoxModel<AutoCompletionItem> model = new AutoCompComboBoxModel<>();
    7878        List<String> keys = new ArrayList<>();
  • test/unit/org/openstreetmap/josm/gui/tagging/presets/items/CheckGroupTest.java

     
    3333        CheckGroup cg = new CheckGroup();
    3434        JPanel p = new JPanel();
    3535        assertEquals(0, p.getComponentCount());
    36         assertFalse(cg.addToPanel(p, TaggingPresetItemGuiSupport.create(false)));
     36        assertFalse(cg.addToPanel(p, TaggingPresetItemGuiSupport.create(false), false));
    3737        assertTrue(p.getComponentCount() > 0);
    3838    }
    3939}
  • test/unit/org/openstreetmap/josm/gui/tagging/presets/items/CheckTest.java

     
    66
    77import javax.swing.JPanel;
    88
    9 import org.junit.jupiter.api.extension.RegisterExtension;
    109import org.junit.jupiter.api.Test;
     10import org.junit.jupiter.api.extension.RegisterExtension;
    1111import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItemGuiSupport;
    1212import org.openstreetmap.josm.testutils.JOSMTestRules;
    1313
     
    3232    void testAddToPanel() {
    3333        JPanel p = new JPanel();
    3434        assertEquals(0, p.getComponentCount());
    35         assertTrue(new Check().addToPanel(p, TaggingPresetItemGuiSupport.create(false)));
     35        assertTrue(new Check().addToPanel(p, TaggingPresetItemGuiSupport.create(false), false));
    3636        assertTrue(p.getComponentCount() > 0);
    3737    }
    3838}
  • test/unit/org/openstreetmap/josm/gui/tagging/presets/items/ComboTest.java

     
    3636    void testAddToPanel() {
    3737        JPanel p = new JPanel();
    3838        assertEquals(0, p.getComponentCount());
    39         assertTrue(new Combo().addToPanel(p, TaggingPresetItemGuiSupport.create(false)));
     39        assertTrue(new Combo().addToPanel(p, TaggingPresetItemGuiSupport.create(false), false));
    4040        assertTrue(p.getComponentCount() > 0);
    4141    }
    4242
     
    5757        Combo.PROP_FILL_DEFAULT.put(false);
    5858        combo.use_last_as_default = 0;
    5959
    60         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, way));
     60        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, way), false);
    6161        assertEquals("", combo.getSelectedItem().value);
    62         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayTagged));
     62        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayTagged), false);
    6363        assertEquals("", combo.getSelectedItem().value);
    64         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT));
     64        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT), false);
    6565        assertEquals("AT", combo.getSelectedItem().value);
    66         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, waySI));
     66        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, waySI), false);
    6767        assertEquals("SI", combo.getSelectedItem().value);
    68         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT, waySI));
     68        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT, waySI), false);
    6969        assertEquals(Combo.DIFFERENT, combo.getSelectedItem().value);
    7070
    7171        combo.default_ = "AT";
    72         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, way));
     72        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, way), false);
    7373        assertEquals("AT", combo.getSelectedItem().value);
    74         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayTagged));
     74        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayTagged), false);
    7575        assertEquals("", combo.getSelectedItem().value);
    76         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT));
     76        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT), false);
    7777        assertEquals("AT", combo.getSelectedItem().value);
    78         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, waySI));
     78        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, waySI), false);
    7979        assertEquals("SI", combo.getSelectedItem().value);
    80         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT, waySI));
     80        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT, waySI), false);
    8181        assertEquals(Combo.DIFFERENT, combo.getSelectedItem().value);
    8282
    8383        Combo.PROP_FILL_DEFAULT.put(true);
    84         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, way));
     84        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, way), false);
    8585        assertEquals("AT", combo.getSelectedItem().value);
    86         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayTagged));
     86        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayTagged), false);
    8787        assertEquals("AT", combo.getSelectedItem().value);
    88         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT));
     88        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT), false);
    8989        assertEquals("AT", combo.getSelectedItem().value);
    90         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, waySI));
     90        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, waySI), false);
    9191        assertEquals("SI", combo.getSelectedItem().value);
    92         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT, waySI));
     92        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT, waySI), false);
    9393        assertEquals(Combo.DIFFERENT, combo.getSelectedItem().value);
    9494        Combo.PROP_FILL_DEFAULT.put(false);
    9595        combo.default_ = null;
    9696
    9797        combo.use_last_as_default = 1; // untagged objects only
    98         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, way));
     98        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, way), false);
    9999        assertEquals("AT", combo.getSelectedItem().value);
    100         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayTagged));
     100        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayTagged), false);
    101101        assertEquals("", combo.getSelectedItem().value);
    102         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT));
     102        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT), false);
    103103        assertEquals("AT", combo.getSelectedItem().value);
    104         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, waySI));
     104        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, waySI), false);
    105105        assertEquals("SI", combo.getSelectedItem().value);
    106         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT, waySI));
     106        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT, waySI), false);
    107107        assertEquals(Combo.DIFFERENT, combo.getSelectedItem().value);
    108108
    109109        combo.use_last_as_default = 2; // "force" on tagged objects too
    110         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, way));
     110        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, way), false);
    111111        assertEquals("AT", combo.getSelectedItem().value);
    112         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayTagged));
     112        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayTagged), false);
    113113        assertEquals("AT", combo.getSelectedItem().value);
    114         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT));
     114        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT), false);
    115115        assertEquals("AT", combo.getSelectedItem().value);
    116         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, waySI));
     116        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, waySI), false);
    117117        assertEquals("SI", combo.getSelectedItem().value);
    118         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT, waySI));
     118        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false, wayAT, waySI), false);
    119119        assertEquals(Combo.DIFFERENT, combo.getSelectedItem().value);
    120120        combo.use_last_as_default = 0;
    121121
     
    129129        combo.values = "red;green;blue;black";
    130130        combo.values_context = "color";
    131131        combo.delimiter = ';';
    132         combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false));
     132        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false), false);
    133133        assertEquals(5, combo.combobox.getItemCount());
    134134        combo.presetListEntries.stream().filter(e -> "red".equals(e.value)).findFirst().ifPresent(combo.combobox::setSelectedItem);
    135135        assertEquals("red", combo.getSelectedItem().value);
  • test/unit/org/openstreetmap/josm/gui/tagging/presets/items/ItemSeparatorTest.java

     
    3232    void testAddToPanel() {
    3333        JPanel p = new JPanel();
    3434        assertEquals(0, p.getComponentCount());
    35         assertFalse(new ItemSeparator().addToPanel(p, TaggingPresetItemGuiSupport.create(false)));
     35        assertFalse(new ItemSeparator().addToPanel(p, TaggingPresetItemGuiSupport.create(false), false));
    3636        assertTrue(p.getComponentCount() > 0);
    3737    }
    3838}
  • test/unit/org/openstreetmap/josm/gui/tagging/presets/items/KeyTest.java

     
    3131    void testAddToPanel() {
    3232        JPanel p = new JPanel();
    3333        assertEquals(0, p.getComponentCount());
    34         assertFalse(new Key().addToPanel(p, TaggingPresetItemGuiSupport.create(false)));
     34        assertFalse(new Key().addToPanel(p, TaggingPresetItemGuiSupport.create(false), false));
    3535        assertEquals(0, p.getComponentCount());
    3636    }
    3737}
  • test/unit/org/openstreetmap/josm/gui/tagging/presets/items/LabelTest.java

     
    3131    void testAddToPanel() {
    3232        JPanel p = new JPanel();
    3333        assertEquals(0, p.getComponentCount());
    34         assertTrue(new Label().addToPanel(p, TaggingPresetItemGuiSupport.create(false)));
     34        assertTrue(new Label().addToPanel(p, TaggingPresetItemGuiSupport.create(false), false));
    3535        assertTrue(p.getComponentCount() > 0);
    3636    }
    3737}
  • test/unit/org/openstreetmap/josm/gui/tagging/presets/items/LinkTest.java

     
    3434        Link l = new Link();
    3535        JPanel p = new JPanel();
    3636        assertEquals(0, p.getComponentCount());
    37         assertFalse(l.addToPanel(p, TaggingPresetItemGuiSupport.create(false)));
     37        assertFalse(l.addToPanel(p, TaggingPresetItemGuiSupport.create(false), false));
    3838        assertEquals(0, p.getComponentCount());
    3939
    4040        l.href = Config.getUrls().getJOSMWebsite();
    41         assertFalse(l.addToPanel(p, TaggingPresetItemGuiSupport.create(false)));
     41        assertFalse(l.addToPanel(p, TaggingPresetItemGuiSupport.create(false), false));
    4242        assertTrue(p.getComponentCount() > 0);
    4343
    4444        l.locale_href = Config.getUrls().getJOSMWebsite();
    45         assertFalse(l.addToPanel(p, TaggingPresetItemGuiSupport.create(false)));
     45        assertFalse(l.addToPanel(p, TaggingPresetItemGuiSupport.create(false), false));
    4646        assertTrue(p.getComponentCount() > 0);
    4747    }
    4848}
  • test/unit/org/openstreetmap/josm/gui/tagging/presets/items/MultiSelectTest.java

     
    3131    void testAddToPanel() {
    3232        JPanel p = new JPanel();
    3333        assertEquals(0, p.getComponentCount());
    34         assertTrue(new MultiSelect().addToPanel(p, TaggingPresetItemGuiSupport.create(false)));
     34        assertTrue(new MultiSelect().addToPanel(p, TaggingPresetItemGuiSupport.create(false), false));
    3535        assertTrue(p.getComponentCount() > 0);
    3636    }
    3737}
  • test/unit/org/openstreetmap/josm/gui/tagging/presets/items/OptionalTest.java

     
    3232    void testAddToPanel() {
    3333        JPanel p = new JPanel();
    3434        assertEquals(0, p.getComponentCount());
    35         assertFalse(new Optional().addToPanel(p, TaggingPresetItemGuiSupport.create(false)));
     35        assertFalse(new Optional().addToPanel(p, TaggingPresetItemGuiSupport.create(false), false));
    3636        assertTrue(p.getComponentCount() > 0);
    3737    }
    3838}
  • test/unit/org/openstreetmap/josm/gui/tagging/presets/items/PresetLinkTest.java

     
    77
    88import javax.swing.JPanel;
    99
    10 import org.junit.jupiter.api.extension.RegisterExtension;
    1110import org.junit.jupiter.api.Test;
     11import org.junit.jupiter.api.extension.RegisterExtension;
    1212import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItemGuiSupport;
    1313import org.openstreetmap.josm.testutils.JOSMTestRules;
    1414
     
    3535        l.preset_name = "River";
    3636        JPanel p = new JPanel();
    3737        assertEquals(0, p.getComponentCount());
    38         assertFalse(l.addToPanel(p, TaggingPresetItemGuiSupport.create(false)));
     38        assertFalse(l.addToPanel(p, TaggingPresetItemGuiSupport.create(false), false));
    3939        assertTrue(p.getComponentCount() > 0);
    4040    }
    4141}
  • test/unit/org/openstreetmap/josm/gui/tagging/presets/items/RolesTest.java

     
    3232    void testAddToPanel() {
    3333        JPanel p = new JPanel();
    3434        assertEquals(0, p.getComponentCount());
    35         assertFalse(new Roles().addToPanel(p, TaggingPresetItemGuiSupport.create(false)));
     35        assertFalse(new Roles().addToPanel(p, TaggingPresetItemGuiSupport.create(false), false));
    3636        assertTrue(p.getComponentCount() > 0);
    3737    }
    3838}
  • test/unit/org/openstreetmap/josm/gui/tagging/presets/items/SpaceTest.java

     
    3232    void testAddToPanel() {
    3333        JPanel p = new JPanel();
    3434        assertEquals(0, p.getComponentCount());
    35         assertFalse(new Space().addToPanel(p, TaggingPresetItemGuiSupport.create(false)));
     35        assertFalse(new Space().addToPanel(p, TaggingPresetItemGuiSupport.create(false), false));
    3636        assertTrue(p.getComponentCount() > 0);
    3737    }
    3838}
  • test/unit/org/openstreetmap/josm/gui/tagging/presets/items/TextTest.java

     
    66
    77import javax.swing.JPanel;
    88
    9 import org.junit.jupiter.api.extension.RegisterExtension;
    109import org.junit.jupiter.api.Test;
     10import org.junit.jupiter.api.extension.RegisterExtension;
    1111import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItemGuiSupport;
    1212import org.openstreetmap.josm.testutils.JOSMTestRules;
    1313
     
    3232    void testAddToPanel() {
    3333        JPanel p = new JPanel();
    3434        assertEquals(0, p.getComponentCount());
    35         assertTrue(new Text().addToPanel(p, TaggingPresetItemGuiSupport.create(false)));
     35        assertTrue(new Text().addToPanel(p, TaggingPresetItemGuiSupport.create(false), false));
    3636        assertTrue(p.getComponentCount() > 0);
    3737    }
    3838}