001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.dialogs.relation;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.BorderLayout;
007import java.awt.FlowLayout;
008import java.awt.event.ActionEvent;
009import java.awt.event.MouseAdapter;
010import java.awt.event.MouseEvent;
011
012import javax.swing.AbstractAction;
013import javax.swing.JButton;
014import javax.swing.JCheckBox;
015import javax.swing.JList;
016import javax.swing.JPanel;
017import javax.swing.JScrollPane;
018import javax.swing.ListSelectionModel;
019import javax.swing.event.ListDataEvent;
020import javax.swing.event.ListDataListener;
021import javax.swing.event.ListSelectionEvent;
022import javax.swing.event.ListSelectionListener;
023
024import org.openstreetmap.josm.data.osm.Relation;
025import org.openstreetmap.josm.gui.MainApplication;
026import org.openstreetmap.josm.gui.PrimitiveRenderer;
027import org.openstreetmap.josm.gui.layer.OsmDataLayer;
028import org.openstreetmap.josm.gui.progress.swing.PleaseWaitProgressMonitor;
029import org.openstreetmap.josm.tools.ImageProvider;
030
031/**
032 * This is browser for a list of relations which refer to another relations.
033 * @since 1806
034 */
035public class ReferringRelationsBrowser extends JPanel {
036
037    /** the list of relations */
038    private JList<Relation> referrers;
039    private final ReferringRelationsBrowserModel model;
040    private final transient OsmDataLayer layer;
041    private final JCheckBox cbReadFull = new JCheckBox(tr("including immediate children of parent relations"));
042    private EditAction editAction;
043
044    /**
045     * Constructs a new {@code ReferringRelationsBrowser}.
046     * @param layer OSM data layer
047     * @param model referring relations browser model
048     */
049    public ReferringRelationsBrowser(OsmDataLayer layer, ReferringRelationsBrowserModel model) {
050        this.model = model;
051        this.layer = layer;
052        build();
053    }
054
055    /**
056     * build the GUI
057     */
058    protected void build() {
059        setLayout(new BorderLayout());
060        referrers = new JList<>(model);
061        referrers.setCellRenderer(new PrimitiveRenderer());
062        add(new JScrollPane(referrers), BorderLayout.CENTER);
063        referrers.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
064        referrers.addMouseListener(new MouseAdapter() {
065            @Override
066            public void mouseClicked(MouseEvent e) {
067                if (e.getClickCount() == 2
068                    && !e.isAltDown() && !e.isAltGraphDown() && !e.isControlDown() && !e.isMetaDown() && !e.isShiftDown()
069                    && referrers.getCellBounds(referrers.getSelectedIndex(), referrers.getSelectedIndex()).contains(e.getPoint())) {
070                    editAction.actionPerformed(new ActionEvent(e.getSource(), ActionEvent.ACTION_PERFORMED, null));
071                }
072            }
073        });
074
075        JPanel pnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
076
077        ReloadAction reloadAction = new ReloadAction();
078        referrers.getModel().addListDataListener(reloadAction);
079        pnl.add(new JButton(reloadAction));
080        pnl.add(cbReadFull);
081
082        editAction = new EditAction();
083        referrers.getSelectionModel().addListSelectionListener(editAction);
084        pnl.add(new JButton(editAction));
085        add(pnl, BorderLayout.SOUTH);
086    }
087
088    public void init() {
089        model.populate(getLayer().data);
090    }
091
092    protected OsmDataLayer getLayer() {
093        return layer;
094    }
095
096    /**
097     * Action for loading the parent relations of a relation
098     *
099     */
100    class ReloadAction extends AbstractAction implements ListDataListener {
101        ReloadAction() {
102            putValue(SHORT_DESCRIPTION, tr("Load parent relations"));
103            new ImageProvider("dialogs", "refresh").getResource().attachImageIcon(this);
104            putValue(NAME, tr("Reload"));
105            refreshEnabled();
106        }
107
108        protected void refreshEnabled() {
109            setEnabled(model.canReload());
110        }
111
112        @Override
113        public void actionPerformed(ActionEvent e) {
114            boolean full = cbReadFull.isSelected();
115            final ParentRelationLoadingTask task = new ParentRelationLoadingTask(
116                    model.getRelation(),
117                    getLayer(),
118                    full,
119                    new PleaseWaitProgressMonitor(tr("Loading parent relations"))
120            );
121            task.setContinuation(() -> {
122                    if (task.isCanceled() || task.hasError())
123                        return;
124                    model.populate(task.getParents());
125                });
126            MainApplication.worker.submit(task);
127        }
128
129        @Override
130        public void contentsChanged(ListDataEvent e) {
131            refreshEnabled();
132        }
133
134        @Override
135        public void intervalAdded(ListDataEvent e) {
136            refreshEnabled();
137        }
138
139        @Override
140        public void intervalRemoved(ListDataEvent e) {
141            refreshEnabled();
142        }
143    }
144
145    /**
146     * Action for editing the currently selected relation
147     *
148     */
149    class EditAction extends AbstractAction implements ListSelectionListener {
150        EditAction() {
151            putValue(SHORT_DESCRIPTION, tr("Edit the currently selected relation"));
152            new ImageProvider("dialogs", "edit").getResource().attachImageIcon(this);
153            putValue(NAME, tr("Edit"));
154            refreshEnabled();
155        }
156
157        protected void refreshEnabled() {
158            setEnabled(referrers.getSelectionModel().getMinSelectionIndex() >= 0);
159        }
160
161        @Override
162        public void actionPerformed(ActionEvent e) {
163            run();
164        }
165
166        public void run() {
167            int idx = referrers.getSelectedIndex();
168            if (idx < 0)
169                return;
170            Relation r = model.getElementAt(idx);
171            if (r == null)
172                return;
173            RelationEditor editor = RelationEditor.getEditor(getLayer(), r, null);
174            editor.setVisible(true);
175        }
176
177        @Override
178        public void valueChanged(ListSelectionEvent e) {
179            refreshEnabled();
180        }
181    }
182}