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.JCheckBox;
014import javax.swing.JList;
015import javax.swing.JPanel;
016import javax.swing.JScrollPane;
017import javax.swing.ListSelectionModel;
018import javax.swing.event.ListDataEvent;
019import javax.swing.event.ListDataListener;
020import javax.swing.event.ListSelectionEvent;
021import javax.swing.event.ListSelectionListener;
022
023import org.openstreetmap.josm.Main;
024import org.openstreetmap.josm.data.osm.Relation;
025import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
026import org.openstreetmap.josm.gui.SideButton;
027import org.openstreetmap.josm.gui.layer.OsmDataLayer;
028import org.openstreetmap.josm.gui.progress.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 JCheckBox cbReadFull;
042    private EditAction editAction;
043
044    /**
045     * build the GUI
046     */
047    protected void build() {
048        setLayout(new BorderLayout());
049        referrers = new JList<>(model);
050        referrers.setCellRenderer(new OsmPrimitivRenderer());
051        add(new JScrollPane(referrers), BorderLayout.CENTER);
052        referrers.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
053        referrers.addMouseListener(new DblClickMouseAdapter());
054
055        JPanel pnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
056
057        ReloadAction reloadAction = new ReloadAction();
058        referrers.getModel().addListDataListener(reloadAction);
059        pnl.add(new SideButton(reloadAction));
060        pnl.add(cbReadFull = new JCheckBox(tr("including immediate children of parent relations")));
061
062        editAction = new EditAction();
063        referrers.getSelectionModel().addListSelectionListener(editAction);
064        pnl.add(new SideButton(editAction));
065        add(pnl, BorderLayout.SOUTH);
066    }
067
068    public ReferringRelationsBrowser(OsmDataLayer layer, ReferringRelationsBrowserModel model) {
069        this.model = model;
070        this.layer = layer;
071        build();
072    }
073
074    public void init() {
075        model.populate(getLayer().data);
076    }
077
078    protected OsmDataLayer getLayer() {
079        return layer;
080    }
081
082    /**
083     * Action for loading the parent relations of a relation
084     *
085     */
086    class ReloadAction extends AbstractAction implements ListDataListener {
087        ReloadAction() {
088            putValue(SHORT_DESCRIPTION, tr("Load parent relations"));
089            putValue(SMALL_ICON, ImageProvider.get("dialogs", "refresh"));
090            putValue(NAME, tr("Reload"));
091            refreshEnabled();
092        }
093
094        protected void refreshEnabled() {
095            setEnabled(model.canReload());
096        }
097
098        @Override
099        public void actionPerformed(ActionEvent e) {
100            boolean full = cbReadFull.isSelected();
101            final ParentRelationLoadingTask task = new ParentRelationLoadingTask(
102                    model.getRelation(),
103                    getLayer(),
104                    full,
105                    new PleaseWaitProgressMonitor(tr("Loading parent relations"))
106            );
107            task.setContinuation(
108                    new Runnable() {
109                        @Override
110                        public void run() {
111                            if (task.isCanceled() || task.hasError())
112                                return;
113                            model.populate(task.getParents());
114                        }
115                    }
116            );
117            Main.worker.submit(task);
118        }
119
120        @Override
121        public void contentsChanged(ListDataEvent e) {
122            refreshEnabled();
123        }
124
125        @Override
126        public void intervalAdded(ListDataEvent e) {
127            refreshEnabled();
128        }
129
130        @Override
131        public void intervalRemoved(ListDataEvent e) {
132            refreshEnabled();
133        }
134    }
135
136    /**
137     * Action for editing the currently selected relation
138     *
139     */
140    class EditAction extends AbstractAction implements ListSelectionListener {
141        EditAction() {
142            putValue(SHORT_DESCRIPTION, tr("Edit the currently selected relation"));
143            putValue(SMALL_ICON, ImageProvider.get("dialogs", "edit"));
144            putValue(NAME, tr("Edit"));
145            refreshEnabled();
146        }
147
148        protected void refreshEnabled() {
149            setEnabled(referrers.getSelectionModel().getMinSelectionIndex() >= 0);
150        }
151
152        @Override
153        public void actionPerformed(ActionEvent e) {
154            run();
155        }
156
157        public void run() {
158            int idx = referrers.getSelectedIndex();
159            if (idx < 0) return;
160            Relation r = model.getElementAt(idx);
161            if (r == null) return;
162            RelationEditor editor = RelationEditor.getEditor(getLayer(), r, null);
163            editor.setVisible(true);
164        }
165
166        @Override
167        public void valueChanged(ListSelectionEvent e) {
168            refreshEnabled();
169        }
170    }
171
172    class DblClickMouseAdapter extends MouseAdapter {
173        @Override
174        public void mouseClicked(MouseEvent e) {
175            if (e.getClickCount() == 2)  {
176                editAction.run();
177            }
178        }
179    }
180}