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.data.imagery.ImageryInfo.ImageryType; 019import org.openstreetmap.josm.gui.widgets.JosmTextArea; 020import org.openstreetmap.josm.gui.widgets.JosmTextField; 021 022/** 023 * An abstract imagery panel used to add WMS/TMS imagery sources. See implementations. 024 * @see AddTMSLayerPanel 025 * @see AddWMSLayerPanel 026 * @since 5617 027 */ 028public abstract class AddImageryPanel extends JPanel { 029 030 protected final JosmTextArea rawUrl = new JosmTextArea(3, 40); 031 protected final JosmTextField name = new JosmTextField(); 032 033 protected final transient Collection<ContentValidationListener> listeners = new ArrayList<>(); 034 035 /** 036 * A listener notified when the validation status of this panel change. 037 */ 038 public interface ContentValidationListener { 039 /** 040 * Called when the validation status of this panel changed 041 * @param isValid true if the conditions required to close this panel are met 042 */ 043 void contentChanged(boolean isValid); 044 } 045 046 protected AddImageryPanel() { 047 this(new GridBagLayout()); 048 } 049 050 protected AddImageryPanel(LayoutManager layout) { 051 super(layout); 052 registerValidableComponent(name); 053 } 054 055 protected final void registerValidableComponent(AbstractButton component) { 056 component.addChangeListener(new ChangeListener() { 057 @Override 058 public void stateChanged(ChangeEvent e) { 059 notifyListeners(); 060 } 061 }); 062 } 063 064 protected final void registerValidableComponent(JTextComponent component) { 065 component.getDocument().addDocumentListener(new DocumentListener() { 066 @Override 067 public void removeUpdate(DocumentEvent e) { 068 notifyListeners(); 069 } 070 071 @Override 072 public void insertUpdate(DocumentEvent e) { 073 notifyListeners(); 074 } 075 076 @Override 077 public void changedUpdate(DocumentEvent e) { 078 notifyListeners(); 079 } 080 }); 081 } 082 083 protected abstract ImageryInfo getImageryInfo(); 084 085 protected static String sanitize(String s) { 086 return s.replaceAll("[\r\n]+", "").trim(); 087 } 088 089 protected static String sanitize(String s, ImageryType type) { 090 String ret = s; 091 String imageryType = type.getTypeString() + ':'; 092 if (ret.startsWith(imageryType)) { 093 // remove ImageryType from URL 094 ret = ret.substring(imageryType.length()); 095 } 096 return sanitize(ret); 097 } 098 099 protected final String getImageryName() { 100 return sanitize(name.getText()); 101 } 102 103 protected final String getImageryRawUrl() { 104 return sanitize(rawUrl.getText()); 105 } 106 107 protected abstract boolean isImageryValid(); 108 109 /** 110 * Registers a new ContentValidationListener 111 * @param l The new ContentValidationListener that will be notified of validation status changes 112 */ 113 public final void addContentValidationListener(ContentValidationListener l) { 114 if (l != null) { 115 listeners.add(l); 116 } 117 } 118 119 private void notifyListeners() { 120 for (ContentValidationListener l : listeners) { 121 l.contentChanged(isImageryValid()); 122 } 123 } 124}