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.osm.DataSelectionListener;
010import org.openstreetmap.josm.data.osm.OsmPrimitive;
011import org.openstreetmap.josm.data.osm.event.SelectionEventManager;
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 * @since 1790
025 */
026public class SelectionTableModel extends AbstractTableModel implements DataSelectionListener, ActiveLayerChangeListener, LayerChangeListener {
027
028    /** this selection table model only displays selected primitives in this layer */
029    private final transient OsmDataLayer layer;
030    private final transient List<OsmPrimitive> cache;
031
032    /**
033     * Creates a new {@link SelectionTableModel} for a given layer
034     *
035     * @param layer  the data layer. Must not be null.
036     * @throws IllegalArgumentException if layer is null
037     */
038    public SelectionTableModel(OsmDataLayer layer) {
039        CheckParameterUtil.ensureParameterNotNull(layer, "layer");
040        this.layer = layer;
041        cache = new ArrayList<>();
042        populateSelectedPrimitives(layer);
043    }
044
045    /**
046     * Registers listeners (selection change and layer change).
047     */
048    public void register() {
049        SelectionEventManager.getInstance().addSelectionListener(this);
050        MainApplication.getLayerManager().addActiveLayerChangeListener(this);
051    }
052
053    /**
054     * Unregisters listeners (selection change and layer change).
055     */
056    public void unregister() {
057        SelectionEventManager.getInstance().removeSelectionListener(this);
058        MainApplication.getLayerManager().removeActiveLayerChangeListener(this);
059    }
060
061    @Override
062    public int getColumnCount() {
063        return 1;
064    }
065
066    @Override
067    public int getRowCount() {
068        if (MainApplication.getLayerManager().getEditLayer() != layer)
069            return 0;
070        return cache.size();
071    }
072
073    @Override
074    public Object getValueAt(int rowIndex, int columnIndex) {
075        return cache.get(rowIndex);
076    }
077
078    @Override
079    public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
080        if (e.getPreviousActiveLayer() == layer) {
081            cache.clear();
082        }
083        if (e.getSource().getActiveLayer() == layer) {
084            cache.addAll(layer.data.getAllSelected());
085        }
086        fireTableDataChanged();
087    }
088
089    @Override
090    public void layerAdded(LayerAddEvent e) {
091        // do nothing
092    }
093
094    @Override
095    public void layerRemoving(LayerRemoveEvent e) {
096        if (e.getRemovedLayer() == layer) {
097            unregister();
098        }
099        this.cache.clear();
100        fireTableDataChanged();
101    }
102
103    @Override
104    public void layerOrderChanged(LayerOrderChangeEvent e) {
105        // do nothing
106    }
107
108    @Override
109    public void selectionChanged(SelectionChangeEvent event) {
110        selectionChanged(event.getSelection());
111    }
112
113    private void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
114        if (layer == MainApplication.getLayerManager().getActiveDataLayer()) {
115            cache.clear();
116            cache.addAll(newSelection);
117        } else {
118            cache.clear();
119        }
120        fireTableDataChanged();
121    }
122
123    /**
124     * Returns the selected primitives.
125     * @return the selected primitives
126     */
127    public List<OsmPrimitive> getSelection() {
128        return cache;
129    }
130
131    /**
132     * populates the model with the primitives currently selected in
133     * <code>layer</code>
134     *
135     * @param layer  the data layer
136     */
137    protected void populateSelectedPrimitives(OsmDataLayer layer) {
138        selectionChanged(layer.data.getAllSelected());
139    }
140
141    /**
142     * Replies the primitive at row <code>row</code> in this model
143     *
144     * @param row the row
145     * @return the primitive at row <code>row</code> in this model
146     * @throws ArrayIndexOutOfBoundsException if index is invalid
147     */
148    public OsmPrimitive getPrimitive(int row) {
149        return cache.get(row);
150    }
151
152}