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        fireTableDataChanged();
084    }
085
086    @Override
087    public void layerAdded(LayerAddEvent e) {
088        // do nothing
089    }
090
091    @Override
092    public void layerRemoving(LayerRemoveEvent e) {
093        if (e.getRemovedLayer() == layer) {
094            unregister();
095        }
096        this.cache.clear();
097        fireTableDataChanged();
098    }
099
100    @Override
101    public void layerOrderChanged(LayerOrderChangeEvent e) {
102        // do nothing
103    }
104
105    @Override
106    public void selectionChanged(SelectionChangeEvent event) {
107        selectionChanged(event.getSelection());
108    }
109
110    private void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
111        if (layer == MainApplication.getLayerManager().getActiveDataLayer()) {
112            cache.clear();
113            cache.addAll(newSelection);
114        } else {
115            cache.clear();
116        }
117        fireTableDataChanged();
118    }
119
120    /**
121     * Returns the selected primitives.
122     * @return the selected primitives
123     */
124    public List<OsmPrimitive> getSelection() {
125        return cache;
126    }
127
128    /**
129     * populates the model with the primitives currently selected in
130     * <code>layer</code>
131     *
132     * @param layer  the data layer
133     */
134    protected void populateSelectedPrimitives(OsmDataLayer layer) {
135        selectionChanged(layer.data.getAllSelected());
136    }
137
138    /**
139     * Replies the primitive at row <code>row</code> in this model
140     *
141     * @param row the row
142     * @return the primitive at row <code>row</code> in this model
143     * @throws ArrayIndexOutOfBoundsException if index is invalid
144     */
145    public OsmPrimitive getPrimitive(int row) {
146        return cache.get(row);
147    }
148
149}