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