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<>(); 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}