/* * Copyright (c) 2012 Data Harmonisation Panel * * All rights reserved. This program and the accompanying materials are made * available under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution. If not, see <http://www.gnu.org/licenses/>. * * Contributors: * HUMBOLDT EU Integrated Project #030962 * Data Harmonisation Panel <http://www.dhpanel.eu> */ package eu.esdihumboldt.hale.ui.io.instance.crs; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.dialogs.TitleAreaDialog; import org.eclipse.jface.preference.FieldEditor; import org.eclipse.jface.preference.StringFieldEditor; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.geotools.referencing.CRS; import org.opengis.referencing.crs.CoordinateReferenceSystem; import eu.esdihumboldt.hale.common.instance.geometry.impl.CodeDefinition; import eu.esdihumboldt.hale.common.instance.geometry.impl.WKTDefinition; import eu.esdihumboldt.hale.common.schema.geometry.CRSDefinition; import eu.esdihumboldt.hale.ui.internal.Messages; /** * Dialog for selecting the CRS to use * * @author Simon Templer * @partner 01 / Fraunhofer Institute for Computer Graphics Research */ public class SelectCRSDialog extends TitleAreaDialog implements IPropertyChangeListener { // private static ALogger _log = ALoggerFactory.getLogger(SelectCRSDialog.class); /** * Text field for editing WKT */ private class WKText { private CoordinateReferenceSystem crs; private String errorMessage; private final Text text; /** * Constructor * * @param parent the parent composite */ public WKText(Composite parent) { text = new Text(parent, SWT.MULTI | SWT.BORDER); text.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { valueChanged(); } }); } /** * Set the text * * @param text the text */ public void setText(String text) { this.text.setText(text); valueChanged(); } /** * Get the text * * @return the text */ public String getText() { return text.getText(); } private void valueChanged() { try { crs = CRS.parseWKT(getText()); errorMessage = "Invalid WKT"; //$NON-NLS-1$ } catch (Exception e) { errorMessage = e.getLocalizedMessage(); crs = null; } updateMessage(); } /** * Get the coordinate reference system * * @return the coordinate reference system */ public WKTDefinition getCRSDefinition() { return new WKTDefinition(getText(), crs); } /** * Returns if the field's value is valid * * @return if the value is valid */ public boolean isValid() { return crs != null; } /** * @return the errorMessage */ public String getErrorMessage() { return errorMessage; } /** * @return the text field */ public Text getTextField() { return text; } } /** * Field editor for a CRS code */ private static class CRSFieldEditor extends StringFieldEditor { private CoordinateReferenceSystem crs; /** * @see StringFieldEditor#doCheckState() */ @Override protected boolean doCheckState() { try { crs = CRS.decode(getStringValue()); boolean valid = crs != null; setErrorMessage("Invalid CRS code"); //$NON-NLS-1$ return valid; } catch (Exception e) { setErrorMessage(e.getMessage()); return false; } } /** * Get the coordinate reference system * * @return the coordinate reference system */ public CodeDefinition getCRSDefinition() { return new CodeDefinition(getStringValue(), crs); } } private static final String DEFAULT_CODE = "EPSG:4326"; //$NON-NLS-1$ private static final String DEFAULT_WKT = "PROJCS[\"MGI (Ferro)/AustriaGKWestZone\",\n" + //$NON-NLS-1$ "\tGEOGCS[\"MGI (Ferro)\",\n" + //$NON-NLS-1$ "\t\tDATUM[\"Militar-Geographische Institut (Ferro)\",\n" + //$NON-NLS-1$ "\t\t\tSPHEROID[\"Bessel 1841\",6377397.155,299.1528128,\n" + //$NON-NLS-1$ "\t\t\tAUTHORITY[\"EPSG\",\"7004\"]],AUTHORITY[\"EPSG\",\"6805\"]],\n" + //$NON-NLS-1$ "\t\tPRIMEM[\"Ferro\",-17.666666666666668,AUTHORITY[\"EPSG\",\"8909\"]],\n" + //$NON-NLS-1$ "\t\tUNIT[\"degree\",0.017453292519943295],\n" + //$NON-NLS-1$ "\t\tAXIS[\"Geodetic latitude\",NORTH],\n" + //$NON-NLS-1$ "\t\tAXIS[\"Geodetic longitude\",EAST],\n" + //$NON-NLS-1$ "\t\tAUTHORITY[\"EPSG\",\"4805\"]],\n" + //$NON-NLS-1$ "\tPROJECTION[\"Transverse Mercator\"],\n" + //$NON-NLS-1$ "PARAMETER[\"central_meridian\",28.0],\n" + //$NON-NLS-1$ "PARAMETER[\"latitude_of_origin\",0.0],\n" + //$NON-NLS-1$ "PARAMETER[\"scale_factor\",1.0],\n" + //$NON-NLS-1$ "PARAMETER[\"false_easting\",0.0],\n" + //$NON-NLS-1$ "PARAMETER[\"false_northing\",-5000000.0],\n" + //$NON-NLS-1$ "UNIT[\"m\",1.0],\n" + //$NON-NLS-1$ "AXIS[\"Y\",EAST],\n" + //$NON-NLS-1$ "AXIS[\"X\",NORTH],\n" + //$NON-NLS-1$ "AUTHORITY[\"EPSG\",\"31251\"]]"; //$NON-NLS-1$ private static String lastCode = DEFAULT_CODE; private static String lastWKT = DEFAULT_WKT; private CRSFieldEditor crsField; private WKText wktField; private static final String DEF_MESSAGE = ""; //$NON-NLS-1$ private Button radioCRS; private Button radioWKT; private Group group; private CRSDefinition value; /** * Constructor * * @param parentShell the parent shell * @param initalValue the initial value */ public SelectCRSDialog(Shell parentShell, CRSDefinition initalValue) { super(parentShell); value = initalValue; } /** * @see TitleAreaDialog#createContents(Composite) */ @Override protected Control createContents(Composite parent) { Control control = super.createContents(parent); setTitle(Messages.SelectCRSDialog_ContentTitle); setMessage(DEF_MESSAGE); updateState(); updateMessage(); return control; } /** * @see Window#configureShell(Shell) */ @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText(Messages.SelectCRSDialog_ShellTitle); } /** * @see TitleAreaDialog#createDialogArea(Composite) */ @Override protected Control createDialogArea(Composite parent) { Composite page = new Composite(parent, SWT.NONE); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); page.setLayoutData(data); page.setLayout(new GridLayout(1, false)); group = new Group(page, SWT.NONE); group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); group.setLayout(new GridLayout(3, false)); group.setText(Messages.SelectCRSDialog_GroupText); SelectionListener radioListener = new SelectionListener() { @Override public void widgetDefaultSelected(SelectionEvent e) { // ignore } @Override public void widgetSelected(SelectionEvent e) { updateSelection(); } }; boolean lastWasCode = value == null || value instanceof CodeDefinition; // CRS string radioCRS = new Button(group, SWT.RADIO); radioCRS.setSelection(lastWasCode); radioCRS.setText(Messages.SelectCRSDialog_RadioCRSText); radioCRS.addSelectionListener(radioListener); crsField = new CRSFieldEditor(); crsField.fillIntoGrid(group, 2); crsField.setEmptyStringAllowed(false); String code; if (value instanceof CodeDefinition) { code = ((CodeDefinition) value).getCode(); } else { code = lastCode; } crsField.setStringValue(code); crsField.setPropertyChangeListener(this); crsField.setEnabled(lastWasCode, group); // WKT string radioWKT = new Button(group, SWT.RADIO); radioWKT.setSelection(!lastWasCode); radioWKT.setText(Messages.SelectCRSDialog_RadioWKTText); radioWKT.addSelectionListener(radioListener); wktField = new WKText(group); wktField.getTextField().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); String wkt; if (value instanceof WKTDefinition) { wkt = ((WKTDefinition) value).getWkt(); } else { wkt = lastWKT; } wktField.setText(wkt); wktField.getTextField().setEnabled(!lastWasCode); return page; } /** * Update the widgets to the radio selection */ protected void updateSelection() { boolean enableCode = radioCRS.getSelection(); crsField.setEnabled(enableCode, group); wktField.getTextField().setEnabled(!enableCode); updateMessage(); updateState(); } /** * @see Dialog#okPressed() */ @Override protected void okPressed() { CRSDefinition crs; if (radioCRS.getSelection()) { crs = crsField.getCRSDefinition(); lastCode = crsField.getCRSDefinition().getCode(); } else { crs = wktField.getCRSDefinition(); lastWKT = wktField.getCRSDefinition().getWkt(); } value = crs; super.okPressed(); } /** * @see Dialog#cancelPressed() */ @Override protected void cancelPressed() { value = null; super.cancelPressed(); } /** * Get the selected value * * @return the selected CRS definition */ public CRSDefinition getValue() { return value; } /** * @see IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) */ @Override public void propertyChange(PropertyChangeEvent event) { if (event.getProperty().equals(FieldEditor.VALUE)) { CRSFieldEditor editor = (CRSFieldEditor) event.getSource(); updateMessage(editor); } else if (event.getProperty().equals(FieldEditor.IS_VALID)) { updateState(); } } /** * Update the dialog message */ private void updateMessage() { if (radioCRS.getSelection()) { updateMessage(crsField); } else { if (wktField.isValid()) { setErrorMessage(null); setMessage(wktField.getCRSDefinition().getCRS().getName().toString(), IMessageProvider.INFORMATION); } else { setErrorMessage(wktField.getErrorMessage()); setMessage(DEF_MESSAGE); } } } /** * Update the dialog message * * @param editor the active editor */ private void updateMessage(CRSFieldEditor editor) { if (editor.isValid()) { setErrorMessage(null); setMessage(editor.getCRSDefinition().getCRS().getName().toString(), IMessageProvider.INFORMATION); } else { setErrorMessage(editor.getErrorMessage()); setMessage(DEF_MESSAGE); } } /** * Update the button state */ private void updateState() { getButton(OK).setEnabled( (radioCRS.getSelection() && crsField.isValid()) || (radioWKT.getSelection() && wktField.isValid())); } }