001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.dialogs.relation;
003import java.util.ArrayList;
004import java.util.Collection;
005import java.util.List;
006
007import javax.swing.table.AbstractTableModel;
008
009import org.openstreetmap.josm.data.SelectionChangedListener;
010import org.openstreetmap.josm.data.osm.DataSet;
011import org.openstreetmap.josm.data.osm.OsmPrimitive;
012import org.openstreetmap.josm.gui.MainApplication;
013import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent;
014import org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener;
015import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent;
016import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent;
017import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent;
018import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
019import org.openstreetmap.josm.gui.layer.OsmDataLayer;
020import org.openstreetmap.josm.tools.CheckParameterUtil;
021
022/**
023 * This table shows the primitives that are currently selected in the main OSM view.
024 */
025public class SelectionTableModel extends AbstractTableModel implements SelectionChangedListener, ActiveLayerChangeListener, LayerChangeListener {
026
027    /** this selection table model only displays selected primitives in this layer */
028    private final transient OsmDataLayer layer;
029    private final transient List<OsmPrimitive> cache;
030
031    /**
032     * Creates a new {@link SelectionTableModel} for a given layer
033     *
034     * @param layer  the data layer. Must not be null.
035     * @throws IllegalArgumentException if layer is null
036     */
037    public SelectionTableModel(OsmDataLayer layer) {
038        CheckParameterUtil.ensureParameterNotNull(layer, "layer");
039        this.layer = layer;
040        cache = new ArrayList<>();
041        populateSelectedPrimitives(layer);
042    }
043
044    /**
045     * Registers listeners (selection change and layer change).
046     */
047    public void register() {
048        DataSet.addSelectionListener(this);
049        MainApplication.getLayerManager().addActiveLayerChangeListener(this);
050    }
051
052    /**
053     * Unregisters listeners (selection change and layer change).
054     */
055    public void unregister() {
056        DataSet.removeSelectionListener(this);
057        MainApplication.getLayerManager().removeActiveLayerChangeListener(this);
058    }
059
060    @Override
061    public int getColumnCount() {
062        return 1;
063    }
064
065    @Override
066    public int getRowCount() {
067        if (MainApplication.getLayerManager().getEditLayer() != layer)
068            return 0;
069        return cache.size();
070    }
071
072    @Override
073    public Object getValueAt(int rowIndex, int columnIndex) {
074        return cache.get(rowIndex);
075    }
076
077    @Override
078    public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
079        if (e.getPreviousActiveLayer() == layer) {
080            cache.clear();
081        }
082        if (e.getSource().getActiveLayer() == layer) {
083            cache.addAll(layer.data.getAllSelected());
084        }
085        fireTableDataChanged();
086    }
087
088    @Override
089    public void layerAdded(LayerAddEvent e) {
090        // do nothing
091    }
092
093    @Override
094    public void layerRemoving(LayerRemoveEvent e) {
095        if (e.getRemovedLayer() == layer) {
096            unregister();
097        }
098        this.cache.clear();
099        fireTableDataChanged();
100    }
101
102    @Override
103    public void layerOrderChanged(LayerOrderChangeEvent e) {
104        // do nothing
105    }
106
107    @Override
108    public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
109        if (layer == MainApplication.getLayerManager().getActiveDataLayer()) {
110            cache.clear();
111            cache.addAll(newSelection);
112        } else {
113            cache.clear();
114        }
115        fireTableDataChanged();
116    }
117
118    public List<OsmPrimitive> getSelection() {
119        return cache;
120    }
121
122    /**
123     * populates the model with the primitives currently selected in
124     * <code>layer</code>
125     *
126     * @param layer  the data layer
127     */
128    protected void populateSelectedPrimitives(OsmDataLayer layer) {
129        selectionChanged(layer.data.getAllSelected());
130    }
131
132    /**
133     * Replies the primitive at row <code>row</code> in this model
134     *
135     * @param row the row
136     * @return the primitive at row <code>row</code> in this model
137     * @throws ArrayIndexOutOfBoundsException if index is invalid
138     */
139    public OsmPrimitive getPrimitive(int row) {
140        return cache.get(row);
141    }
142
143}