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.BorderLayout;
008import java.beans.PropertyChangeEvent;
009import java.beans.PropertyChangeListener;
010
011import javax.swing.BorderFactory;
012import javax.swing.JLabel;
013import javax.swing.JPanel;
014import javax.swing.event.HyperlinkEvent;
015import javax.swing.event.HyperlinkListener;
016
017import org.openstreetmap.josm.data.osm.Changeset;
018import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
019import org.openstreetmap.josm.io.Capabilities;
020import org.openstreetmap.josm.io.OsmApi;
021import org.openstreetmap.josm.io.UploadStrategySpecification;
022import org.openstreetmap.josm.tools.ImageProvider;
023
024/**
025 * A panel that displays a summary of data the user is about to upload
026 * <p>
027 * FIXME this class should extend HtmlPanel instead (duplicated code in here)
028 */
029public class UploadParameterSummaryPanel extends JPanel implements HyperlinkListener, PropertyChangeListener {
030    private transient UploadStrategySpecification spec = new UploadStrategySpecification();
031    private int numObjects;
032    private JMultilineLabel jepMessage;
033    private JLabel lblWarning;
034
035    private transient Changeset selectedChangeset;
036    private boolean closeChangesetAfterNextUpload;
037    private transient ConfigurationParameterRequestHandler configHandler;
038
039    /**
040     * Constructs a new {@code UploadParameterSummaryPanel}.
041     */
042    public UploadParameterSummaryPanel() {
043        build();
044        updateSummary();
045    }
046
047    protected String buildChangesetSummary() {
048        StringBuilder msg = new StringBuilder(96);
049        if (selectedChangeset == null || selectedChangeset.isNew()) {
050            msg.append(tr("Objects are uploaded to a <strong>new changeset</strong>."));
051        } else {
052            msg.append(tr("Objects are uploaded to the <strong>open changeset</strong> {0} with upload comment ''{1}''.",
053                    selectedChangeset.getId(),
054                    selectedChangeset.getComment()
055            ));
056        }
057        msg.append(' ');
058        if (closeChangesetAfterNextUpload) {
059            msg.append(tr("The changeset is going to be <strong>closed</strong> after this upload"));
060        } else {
061            msg.append(tr("The changeset is <strong>left open</strong> after this upload"));
062        }
063        msg.append(" (<a href=\"urn:changeset-configuration\">").append(tr("configure changeset")).append("</a>)");
064        return msg.toString();
065    }
066
067    protected String buildStrategySummary() {
068        if (spec == null)
069            return "";
070        // check whether we can use one changeset only or whether we have to use multiple changesets
071        //
072        boolean useOneChangeset = true;
073        Capabilities capabilities = OsmApi.getOsmApi().getCapabilities();
074        int maxChunkSize = capabilities != null ? capabilities.getMaxChangesetSize() : -1;
075        if (maxChunkSize > 0 && numObjects > maxChunkSize) {
076            useOneChangeset = false;
077        }
078
079        int numRequests = spec.getNumRequests(numObjects);
080        String msg = null;
081        if (useOneChangeset) {
082            lblWarning.setVisible(false);
083            if (numRequests == 0) {
084                msg = trn(
085                        "Uploading <strong>{0} object</strong> to <strong>1 changeset</strong>",
086                        "Uploading <strong>{0} objects</strong> to <strong>1 changeset</strong>",
087                        numObjects, numObjects
088                );
089            } else if (numRequests == 1) {
090                msg = trn(
091                        "Uploading <strong>{0} object</strong> to <strong>1 changeset</strong> using <strong>1 request</strong>",
092                        "Uploading <strong>{0} objects</strong> to <strong>1 changeset</strong> using <strong>1 request</strong>",
093                        numObjects, numObjects
094                );
095            } else if (numRequests > 1) {
096                msg = tr("Uploading <strong>{0} objects</strong> to <strong>1 changeset</strong> using <strong>{1} requests</strong>",
097                        numObjects, numRequests);
098            }
099            msg = msg + " (<a href=\"urn:advanced-configuration\">" + tr("advanced configuration") + "</a>)";
100        } else {
101            lblWarning.setVisible(true);
102            if (numRequests == 0) {
103                msg = tr("{0} objects exceed the max. allowed {1} objects in a changeset on the server ''{2}''. " +
104                        "Please <a href=\"urn:advanced-configuration\">configure</a> how to proceed with <strong>multiple changesets</strong>",
105                        numObjects, maxChunkSize, OsmApi.getOsmApi().getBaseUrl());
106            } else if (numRequests > 1) {
107                msg = tr("Uploading <strong>{0} objects</strong> to <strong>multiple changesets</strong> using <strong>{1} requests</strong>",
108                        numObjects, numRequests);
109                msg = msg + " (<a href=\"urn:advanced-configuration\">" + tr("advanced configuration") + "</a>)";
110            }
111        }
112        return msg;
113    }
114
115    protected void build() {
116        jepMessage = new JMultilineLabel("");
117        jepMessage.addHyperlinkListener(this);
118
119        setLayout(new BorderLayout());
120        add(jepMessage, BorderLayout.CENTER);
121        lblWarning = new JLabel("");
122        lblWarning.setVisible(false);
123        lblWarning.setLabelFor(jepMessage);
124        lblWarning.setIcon(ImageProvider.get("warning-small"));
125        lblWarning.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
126        JPanel pnl = new JPanel(new BorderLayout());
127        pnl.add(lblWarning, BorderLayout.NORTH);
128        add(pnl, BorderLayout.WEST);
129    }
130
131    public void setConfigurationParameterRequestListener(ConfigurationParameterRequestHandler handler) {
132        this.configHandler = handler;
133    }
134
135    /**
136     * Sets the {@link UploadStrategySpecification} the user chose
137     * @param spec The specification to display
138     */
139    public void setUploadStrategySpecification(UploadStrategySpecification spec) {
140        this.spec = spec;
141        updateSummary();
142    }
143
144    /**
145     * Sets the number of objects that will be uploaded
146     * @param numObjects The number to display
147     */
148    public void setNumObjects(int numObjects) {
149        this.numObjects = numObjects;
150        updateSummary();
151    }
152
153    /**
154     * Display that the changeset will be closed after the upload
155     * @param value <code>true</code> if it will be closed
156     */
157    public void setCloseChangesetAfterNextUpload(boolean value) {
158        this.closeChangesetAfterNextUpload = value;
159        updateSummary();
160    }
161
162    protected void updateSummary() {
163        StringBuilder sb = new StringBuilder(32);
164        sb.append("<html>")
165          .append(buildStrategySummary())
166          .append("<br><br>")
167          .append(buildChangesetSummary())
168          .append("</html>");
169        jepMessage.setText(sb.toString());
170    }
171
172    /* --------------------------------------------------------------------- */
173    /* Interface HyperlinkListener
174    /* --------------------------------------------------------------------- */
175    @Override
176    public void hyperlinkUpdate(HyperlinkEvent e) {
177        if (HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType())) {
178            String desc = e.getDescription();
179            if (desc == null || configHandler == null)
180                return;
181            if ("urn:changeset-configuration".equals(desc)) {
182                configHandler.handleChangesetConfigurationRequest();
183            } else if ("urn:advanced-configuration".equals(desc)) {
184                configHandler.handleUploadStrategyConfigurationRequest();
185            }
186        }
187    }
188
189    /* --------------------------------------------------------------------- */
190    /* Interface PropertyChangeListener
191    /* --------------------------------------------------------------------- */
192    @Override
193    public void propertyChange(PropertyChangeEvent evt) {
194        if (evt.getPropertyName().equals(ChangesetManagementPanel.SELECTED_CHANGESET_PROP)) {
195            selectedChangeset = (Changeset) evt.getNewValue();
196            updateSummary();
197        } else if (evt.getPropertyName().equals(ChangesetManagementPanel.CLOSE_CHANGESET_AFTER_UPLOAD)) {
198            closeChangesetAfterNextUpload = (Boolean) evt.getNewValue();
199            updateSummary();
200        } else if (evt.getPropertyName().equals(UploadedObjectsSummaryPanel.NUM_OBJECTS_TO_UPLOAD_PROP)) {
201            numObjects = (Integer) evt.getNewValue();
202            updateSummary();
203        } else if (evt.getPropertyName().equals(UploadStrategySelectionPanel.UPLOAD_STRATEGY_SPECIFICATION_PROP)) {
204            this.spec = (UploadStrategySpecification) evt.getNewValue();
205            updateSummary();
206        }
207    }
208}