001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.io;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005import static org.openstreetmap.josm.tools.I18n.trn;
006
007import java.awt.GridBagConstraints;
008import java.awt.GridBagLayout;
009import java.util.ArrayList;
010import java.util.List;
011
012import javax.swing.AbstractListModel;
013import javax.swing.JLabel;
014import javax.swing.JList;
015import javax.swing.JPanel;
016import javax.swing.JScrollPane;
017
018import org.openstreetmap.josm.data.osm.OsmPrimitive;
019import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
020
021/**
022 * This panel displays a summary of the objects to upload. It is displayed in the upper part of the {@link UploadDialog}.
023 * @since 2599
024 */
025public class UploadedObjectsSummaryPanel extends JPanel {
026    public static final String NUM_OBJECTS_TO_UPLOAD_PROP = UploadedObjectsSummaryPanel.class.getName() + ".numObjectsToUpload";
027
028    /** the list with the added primitives */
029    private PrimitiveList lstAdd;
030    private JLabel lblAdd;
031    private JScrollPane spAdd;
032    /** the list with the updated primitives */
033    private PrimitiveList lstUpdate;
034    private JLabel lblUpdate;
035    private JScrollPane spUpdate;
036    /** the list with the deleted primitives */
037    private PrimitiveList lstDelete;
038    private JLabel lblDelete;
039    private JScrollPane spDelete;
040
041    /**
042     * Constructs a new {@code UploadedObjectsSummaryPanel}.
043     */
044    public UploadedObjectsSummaryPanel() {
045        build();
046    }
047
048    protected void build() {
049        setLayout(new GridBagLayout());
050        OsmPrimitivRenderer renderer = new OsmPrimitivRenderer();
051        // initialize the three lists for uploaded primitives, but don't add them to the dialog yet, see setUploadedPrimitives()
052        //
053        lstAdd = new PrimitiveList();
054        lstAdd.setCellRenderer(renderer);
055        lstAdd.setVisibleRowCount(Math.min(lstAdd.getModel().getSize(), 10));
056        spAdd = new JScrollPane(lstAdd);
057        lblAdd = new JLabel(tr("Objects to add:"));
058        lblAdd.setLabelFor(lstAdd);
059
060        lstUpdate = new PrimitiveList();
061        lstUpdate.setCellRenderer(renderer);
062        lstUpdate.setVisibleRowCount(Math.min(lstUpdate.getModel().getSize(), 10));
063        spUpdate = new JScrollPane(lstUpdate);
064        lblUpdate = new JLabel(tr("Objects to modify:"));
065        lblUpdate.setLabelFor(lstUpdate);
066
067        lstDelete = new PrimitiveList();
068        lstDelete.setCellRenderer(renderer);
069        lstDelete.setVisibleRowCount(Math.min(lstDelete.getModel().getSize(), 10));
070        spDelete = new JScrollPane(lstDelete);
071        lblDelete = new JLabel(tr("Objects to delete:"));
072        lblDelete.setLabelFor(lstDelete);
073    }
074
075    /**
076     * Sets the collections of primitives which will be uploaded
077     *
078     * @param add  the collection of primitives to add
079     * @param update the collection of primitives to update
080     * @param delete the collection of primitives to delete
081     */
082    public void setUploadedPrimitives(List<OsmPrimitive> add, List<OsmPrimitive> update, List<OsmPrimitive> delete) {
083        lstAdd.getPrimitiveListModel().setPrimitives(add);
084        lstUpdate.getPrimitiveListModel().setPrimitives(update);
085        lstDelete.getPrimitiveListModel().setPrimitives(delete);
086
087        GridBagConstraints gcLabel = new GridBagConstraints();
088        gcLabel.fill = GridBagConstraints.HORIZONTAL;
089        gcLabel.weightx = 1.0;
090        gcLabel.weighty = 0.0;
091        gcLabel.anchor = GridBagConstraints.FIRST_LINE_START;
092
093        GridBagConstraints gcList = new GridBagConstraints();
094        gcList.fill = GridBagConstraints.BOTH;
095        gcList.weightx = 1.0;
096        gcList.weighty = 1.0;
097        gcList.anchor = GridBagConstraints.CENTER;
098        removeAll();
099        int y = -1;
100        if (!add.isEmpty()) {
101            y++;
102            gcLabel.gridy = y;
103            lblAdd.setText(trn("{0} object to add:", "{0} objects to add:", add.size(), add.size()));
104            add(lblAdd, gcLabel);
105            y++;
106            gcList.gridy = y;
107            add(spAdd, gcList);
108        }
109        if (!update.isEmpty()) {
110            y++;
111            gcLabel.gridy = y;
112            lblUpdate.setText(trn("{0} object to modify:", "{0} objects to modify:", update.size(), update.size()));
113            add(lblUpdate, gcLabel);
114            y++;
115            gcList.gridy = y;
116            add(spUpdate, gcList);
117        }
118        if (!delete.isEmpty()) {
119            y++;
120            gcLabel.gridy = y;
121            lblDelete.setText(trn("{0} object to delete:", "{0} objects to delete:", delete.size(), delete.size()));
122            add(lblDelete, gcLabel);
123            y++;
124            gcList.gridy = y;
125            add(spDelete, gcList);
126        }
127
128        firePropertyChange(NUM_OBJECTS_TO_UPLOAD_PROP, 0, getNumObjectsToUpload());
129    }
130
131    /**
132     * Replies the number of objects to upload
133     *
134     * @return the number of objects to upload
135     */
136    public int getNumObjectsToUpload() {
137        return lstAdd.getModel().getSize()
138        + lstUpdate.getModel().getSize()
139        + lstDelete.getModel().getSize();
140    }
141
142    /**
143     * A simple list of OSM primitives.
144     */
145    static class PrimitiveList extends JList<OsmPrimitive> {
146        /**
147         * Constructs a new {@code PrimitiveList}.
148         */
149        PrimitiveList() {
150            super(new PrimitiveListModel());
151        }
152
153        public PrimitiveListModel getPrimitiveListModel() {
154            return (PrimitiveListModel) getModel();
155        }
156    }
157
158    /**
159     * A list model for a list of OSM primitives.
160     */
161    static class PrimitiveListModel extends AbstractListModel<OsmPrimitive> {
162        private transient List<OsmPrimitive> primitives;
163
164        /**
165         * Constructs a new {@code PrimitiveListModel}.
166         */
167        PrimitiveListModel() {
168            primitives = new ArrayList<>();
169        }
170
171        PrimitiveListModel(List<OsmPrimitive> primitives) {
172            setPrimitives(primitives);
173        }
174
175        public void setPrimitives(List<OsmPrimitive> primitives) {
176            if (primitives == null) {
177                this.primitives = new ArrayList<>();
178            } else {
179                this.primitives = primitives;
180            }
181            fireContentsChanged(this, 0, getSize());
182        }
183
184        @Override
185        public OsmPrimitive getElementAt(int index) {
186            if (primitives == null) return null;
187            return primitives.get(index);
188        }
189
190        @Override
191        public int getSize() {
192            if (primitives == null) return 0;
193            return primitives.size();
194        }
195    }
196}