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