001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.preferences.imagery;
003
004import java.awt.GridBagLayout;
005import java.awt.LayoutManager;
006import java.util.ArrayList;
007import java.util.Collection;
008
009import javax.swing.AbstractButton;
010import javax.swing.JPanel;
011import javax.swing.event.ChangeEvent;
012import javax.swing.event.ChangeListener;
013import javax.swing.event.DocumentEvent;
014import javax.swing.event.DocumentListener;
015import javax.swing.text.JTextComponent;
016
017import org.openstreetmap.josm.data.imagery.ImageryInfo;
018import org.openstreetmap.josm.gui.widgets.JosmTextArea;
019import org.openstreetmap.josm.gui.widgets.JosmTextField;
020
021/**
022 * An abstract imagery panel used to add WMS/TMS imagery sources. See implementations.
023 * @see AddTMSLayerPanel
024 * @see AddWMSLayerPanel
025 * @since 5617
026 */
027public abstract class AddImageryPanel extends JPanel {
028
029    protected final JosmTextArea rawUrl = new JosmTextArea(3, 40);
030    protected final JosmTextField name = new JosmTextField();
031
032    protected final Collection<ContentValidationListener> listeners = new ArrayList<ContentValidationListener>();
033
034    /**
035     * A listener notified when the validation status of this panel change.
036     */
037    public interface ContentValidationListener {
038        /**
039         * Called when the validation status of this panel changed
040         * @param isValid true if the conditions required to close this panel are met
041         */
042        public void contentChanged(boolean isValid);
043    }
044
045    protected AddImageryPanel() {
046        this(new GridBagLayout());
047    }
048
049    protected AddImageryPanel(LayoutManager layout) {
050        super(layout);
051        registerValidableComponent(name);
052    }
053
054    protected final void registerValidableComponent(AbstractButton component) {
055        component.addChangeListener(new ChangeListener() {
056            @Override public void stateChanged(ChangeEvent e) { notifyListeners(); }
057        });
058    }
059
060    protected final void registerValidableComponent(JTextComponent component) {
061        component.getDocument().addDocumentListener(new DocumentListener() {
062            @Override public void removeUpdate(DocumentEvent e) { notifyListeners(); }
063            @Override public void insertUpdate(DocumentEvent e) { notifyListeners(); }
064            @Override public void changedUpdate(DocumentEvent e) { notifyListeners(); }
065        });
066    }
067
068    protected abstract ImageryInfo getImageryInfo();
069
070    protected static String sanitize(String s) {
071        return s.replaceAll("[\r\n]+", "").trim();
072    }
073
074    protected final String getImageryName() {
075        return sanitize(name.getText());
076    }
077
078    protected final String getImageryRawUrl() {
079        return sanitize(rawUrl.getText());
080    }
081
082    protected abstract boolean isImageryValid();
083
084    /**
085     * Registers a new ContentValidationListener
086     * @param l The new ContentValidationListener that will be notified of validation status changes
087     */
088    public final void addContentValidationListener(ContentValidationListener l) {
089        if (l != null) {
090            listeners.add(l);
091        }
092    }
093
094    private final void notifyListeners() {
095        for (ContentValidationListener l : listeners) {
096            l.contentChanged(isImageryValid());
097        }
098    }
099}