Index: /trunk/src/org/openstreetmap/josm/gui/io/UploadStrategySelectionPanel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/io/UploadStrategySelectionPanel.java	(revision 16971)
+++ /trunk/src/org/openstreetmap/josm/gui/io/UploadStrategySelectionPanel.java	(revision 16972)
@@ -5,5 +5,4 @@
 import static org.openstreetmap.josm.tools.I18n.trn;
 
-import java.awt.Color;
 import java.awt.Component;
 import java.awt.GridBagConstraints;
@@ -22,13 +21,11 @@
 import java.util.Map.Entry;
 
-import javax.swing.BorderFactory;
 import javax.swing.ButtonGroup;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JRadioButton;
-import javax.swing.UIManager;
-import javax.swing.event.DocumentEvent;
-import javax.swing.event.DocumentListener;
-
+import javax.swing.text.JTextComponent;
+
+import org.openstreetmap.josm.gui.widgets.AbstractTextComponentValidator;
 import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
 import org.openstreetmap.josm.gui.widgets.JosmTextField;
@@ -54,6 +51,4 @@
     public static final String UPLOAD_STRATEGY_SPECIFICATION_PROP =
         UploadStrategySelectionPanel.class.getName() + ".uploadStrategySpecification";
-
-    private static final Color BG_COLOR_ERROR = new Color(255, 224, 224);
 
     private transient Map<UploadStrategy, JRadioButton> rbStrategy;
@@ -174,5 +169,5 @@
 
         tfChunkSize.addFocusListener(new TextFieldFocusHandler());
-        tfChunkSize.getDocument().addDocumentListener(new ChunkSizeInputVerifier());
+        new ChunkSizeValidator(tfChunkSize);
 
         StrategyChangeListener strategyChangeListener = new StrategyChangeListener();
@@ -420,36 +415,29 @@
     }
 
-    class ChunkSizeInputVerifier implements DocumentListener, PropertyChangeListener {
-        protected void setErrorFeedback(JosmTextField tf, String message) {
-            tf.setBorder(BorderFactory.createLineBorder(Color.RED, 1));
-            tf.setToolTipText(message);
-            tf.setBackground(BG_COLOR_ERROR);
-        }
-
-        protected void clearErrorFeedback(JosmTextField tf, String message) {
-            tf.setBorder(UIManager.getBorder("TextField.border"));
-            tf.setToolTipText(message);
-            tf.setBackground(UIManager.getColor("TextField.background"));
-        }
-
-        protected void validateChunkSize() {
+    class ChunkSizeValidator extends AbstractTextComponentValidator {
+        ChunkSizeValidator(JTextComponent tc) {
+            super(tc);
+        }
+
+        @Override
+        public void validate() {
             try {
                 int chunkSize = Integer.parseInt(tfChunkSize.getText().trim());
                 int maxChunkSize = OsmApi.getOsmApi().getCapabilities().getMaxChangesetSize();
                 if (chunkSize <= 0) {
-                    setErrorFeedback(tfChunkSize, tr("Illegal chunk size <= 0. Please enter an integer > 1"));
+                    feedbackInvalid(tr("Illegal chunk size <= 0. Please enter an integer > 1"));
                 } else if (maxChunkSize > 0 && chunkSize > maxChunkSize) {
-                    setErrorFeedback(tfChunkSize, tr("Chunk size {0} exceeds max. changeset size {1} for server ''{2}''",
+                    feedbackInvalid(tr("Chunk size {0} exceeds max. changeset size {1} for server ''{2}''",
                             chunkSize, maxChunkSize, OsmApi.getOsmApi().getBaseUrl()));
                 } else {
-                    clearErrorFeedback(tfChunkSize, tr("Please enter an integer > 1"));
+                    feedbackValid(null);
                 }
 
                 if (maxChunkSize > 0 && chunkSize > maxChunkSize) {
-                    setErrorFeedback(tfChunkSize, tr("Chunk size {0} exceeds max. changeset size {1} for server ''{2}''",
+                    feedbackInvalid(tr("Chunk size {0} exceeds max. changeset size {1} for server ''{2}''",
                             chunkSize, maxChunkSize, OsmApi.getOsmApi().getBaseUrl()));
                 }
             } catch (NumberFormatException e) {
-                setErrorFeedback(tfChunkSize, tr("Value ''{0}'' is not a number. Please enter an integer > 1",
+                feedbackInvalid(tr("Value ''{0}'' is not a number. Please enter an integer > 1",
                         tfChunkSize.getText().trim()));
             } finally {
@@ -459,26 +447,6 @@
 
         @Override
-        public void changedUpdate(DocumentEvent e) {
-            validateChunkSize();
-        }
-
-        @Override
-        public void insertUpdate(DocumentEvent e) {
-            validateChunkSize();
-        }
-
-        @Override
-        public void removeUpdate(DocumentEvent e) {
-            validateChunkSize();
-        }
-
-        @Override
-        public void propertyChange(PropertyChangeEvent evt) {
-            if (evt.getSource() == tfChunkSize
-                    && "enabled".equals(evt.getPropertyName())
-                    && (Boolean) evt.getNewValue()
-            ) {
-                validateChunkSize();
-            }
+        public boolean isValid() {
+            throw new UnsupportedOperationException();
         }
     }
