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