001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.dialogs.properties;
003
004import java.awt.Cursor;
005import java.awt.Dimension;
006import java.awt.Font;
007import java.awt.GridBagLayout;
008import java.awt.event.MouseEvent;
009import java.awt.event.MouseListener;
010import java.awt.font.TextAttribute;
011import java.util.Collection;
012import java.util.Collections;
013import java.util.List;
014import java.util.Map;
015
016import javax.swing.Action;
017import javax.swing.Icon;
018import javax.swing.JLabel;
019import javax.swing.JPanel;
020
021import org.openstreetmap.josm.data.osm.OsmPrimitive;
022import org.openstreetmap.josm.data.osm.Tag;
023import org.openstreetmap.josm.gui.tagging.TaggingPreset;
024import org.openstreetmap.josm.gui.tagging.TaggingPresetType;
025import org.openstreetmap.josm.tools.GBC;
026
027public class PresetListPanel extends JPanel {
028
029    public PresetListPanel() {
030        super(new GridBagLayout());
031    }
032
033    public interface PresetHandler {
034        Collection<OsmPrimitive> getSelection();
035        void updateTags(List<Tag> tags);
036    }
037
038    /**
039     * Small helper class that manages the highlighting of the label on hover as well as opening
040     * the corresponding preset when clicked
041     */
042    private static class PresetLabelML implements MouseListener {
043        final JLabel label;
044        final Font hover;
045        final Font normal;
046        final TaggingPreset tag;
047        final PresetHandler presetHandler;
048
049        PresetLabelML(JLabel lbl, TaggingPreset t, PresetHandler presetHandler) {
050            super();
051            label = lbl;
052            lbl.setCursor(new Cursor(Cursor.HAND_CURSOR));
053            normal = label.getFont();
054            hover = normal.deriveFont(Collections.singletonMap(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_LOW_DOTTED));
055            tag = t;
056            this.presetHandler = presetHandler;
057        }
058        @Override
059        public void mouseClicked(MouseEvent arg0) {
060            Collection<OsmPrimitive> selection = tag.createSelection(presetHandler.getSelection());
061            if (selection == null || selection.isEmpty())
062                return;
063            int answer = tag.showDialog(selection, false);
064
065            if (answer == TaggingPreset.DIALOG_ANSWER_APPLY) {
066                presetHandler.updateTags(tag.getChangedTags());
067            }
068
069        }
070        @Override
071        public void mouseEntered(MouseEvent arg0) {
072            label.setFont(hover);
073        }
074        @Override
075        public void mouseExited(MouseEvent arg0) {
076            label.setFont(normal);
077        }
078        @Override
079        public void mousePressed(MouseEvent arg0) {}
080        @Override
081        public void mouseReleased(MouseEvent arg0) {}
082    }
083
084    public void updatePresets(final Collection<TaggingPresetType> types, final Map<String, String> tags, PresetHandler presetHandler) {
085
086        removeAll();
087        if (types.isEmpty()) {
088            setVisible(false);
089            return;
090        }
091
092        for (TaggingPreset t : TaggingPreset.getMatchingPresets(types, tags, true)) {
093            JLabel lbl = new JLabel(t.getName() + " …");
094            lbl.setIcon(t.getIcon());
095            lbl.addMouseListener(new PresetLabelML(lbl, t, presetHandler));
096            add(lbl, GBC.eol().fill(GBC.HORIZONTAL));
097        }
098
099        if (getComponentCount() > 0) {
100            setVisible(true);
101            // This ensures the presets are exactly as high as needed.
102            int height = getComponentCount() * getComponent(0).getHeight();
103            Dimension size = new Dimension(getWidth(), height);
104            setMaximumSize(size);
105            setMinimumSize(size);
106        } else {
107            setVisible(false);
108        }
109    }
110}