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}