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