Java tutorial
/* uDig - User Friendly Desktop Internet GIS client * http://udig.refractions.net * (C) 2004, Refractions Research Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package net.refractions.udig.catalog.ui.operation; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.ArrayList; import java.util.List; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import net.miginfocom.swt.MigLayout; import net.refractions.udig.internal.ui.UDigByteAndLocalTransfer; import net.refractions.udig.ui.filter.ExpressionInput; import net.refractions.udig.ui.filter.ExpressionViewer; import net.refractions.udig.ui.filter.IExpressionViewer; import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.Preferences.IPropertyChangeListener; import org.eclipse.jface.fieldassist.ControlDecoration; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.util.SafeRunnable; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.ViewerDropAdapter; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.DragSourceAdapter; import org.eclipse.swt.dnd.DragSourceEvent; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.dnd.TransferData; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.geotools.factory.CommonFactoryFinder; import org.geotools.filter.text.ecql.ECQL; import org.geotools.process.feature.gs.TransformProcess; import org.geotools.process.feature.gs.TransformProcess.Definition; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.AttributeDescriptor; import org.opengis.filter.FilterFactory2; import org.opengis.filter.expression.Expression; /** * Panel that can be places in a UI used to ask the user to enter in a series of expression for use * with the Transform process. * * @author leviputna */ public class TransformPanel extends Composite { /** * A definition value has been modified */ public static final String MODIFY = "Modify"; /** * The list of definitions has been reorded */ public static final String ORDER = "Order"; private static final String NO_CONTENT = "--"; private List<TransformProcess.Definition> transform; private ControlDecoration feedbackDecorator; private SimpleFeature sample; private Text name; private IExpressionViewer expression; private SimpleFeatureType schema; private Composite composite; /** * List of change listeners * * @see #fireChanged */ private ListenerList changedListeners = new ListenerList(); static List<Definition> createDefaultTransformDefinition(SimpleFeatureType featureType) { FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(); List<Definition> list = new ArrayList<TransformProcess.Definition>(); if (featureType != null) { for (AttributeDescriptor descriptor : featureType.getAttributeDescriptors()) { Definition definition = new Definition(); definition.name = descriptor.getLocalName(); definition.binding = descriptor.getType().getBinding(); definition.expression = ff.property(descriptor.getName()); list.add(definition); } } return list; } /** * viewer used to review {@link #transform} */ private TableViewer table; private ModifyListener nameListener = new ModifyListener() { public void modifyText(ModifyEvent e) { Definition definition = selectedDefinition(); String text = name.getText(); if (definition.name == null || !definition.name.equals(text)) { definition.name = text; // refresh the display, including labels and display the row if needed table.refresh(definition, true, true); ; fireChanged(new ChangeEvent(transform)); } } }; private ISelectionChangedListener expressionListener = new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { Definition definition = selectedDefinition(); Expression expr = expression.getExpression(); if (definition.expression == null || !definition.equals(expr)) { definition.expression = expr; try { Object value = definition.expression.evaluate(sample); definition.binding = value.getClass(); } catch (Throwable t) { definition.binding = null; // unknown } // refresh the display, including labels and display the row if needed table.refresh(definition, true, true); } } }; private ISelectionChangedListener tableListener = new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { Definition definition = selectedDefinition(); listen(false); try { if (definition == null) { name.setText(""); expression.setExpression(Expression.NIL); enable(false); } else { name.setText(definition.name); expression.setExpression(definition.expression); enable(true); } } finally { listen(true); } } }; private Label definitionLabel; /** * Create the composite UI elements. * <p> * Only UI elements that are common to all implementations of this Composite should be added * here, Finish, Next and Done buttons are specific to form or wizard implementations and should * not be added here. * </p> * <p> * Recommend using the Design tab as it will help maintain layout. * </p> * * @param parent * @param style */ public TransformPanel(Composite parent, int style) { super(parent, style); // setup the table part of the panel createExpressionTable(parent); this.listen(true); } /* * (non-Javadoc) Method declared on ISelectionProvider. */ public void addChangedListener(ChangeListener listener) { changedListeners.add(listener); } /* * (non-Javadoc) Method declared on ISelectionProvider. */ public void removeChangedListener(ChangeListener listener) { changedListeners.remove(listener); } /** * Notifies any selection changed listeners that the viewer's selection has changed. Only * listeners registered at the time this method is called are notified. * * @param changeEvent a selection changed event * * @see ISelectionChangedListener#selectionChanged */ protected void fireChanged(final ChangeEvent changeEvent) { Object[] listeners = changedListeners.getListeners(); for (int i = 0; i < listeners.length; ++i) { ((ChangeListener) listeners[i]).stateChanged(changeEvent); } } public void setInput(SimpleFeature sample) { listen(false); this.schema = sample.getFeatureType(); this.sample = sample; this.transform = createDefaultTransformDefinition(schema); table.setInput(this.transform); table.refresh(); ExpressionInput expressionInput = new ExpressionInput(schema, true); expressionInput.setFeedback(feedbackDecorator); expression.setInput(expressionInput); expression.refresh(); listen(true); } /** * Get the Composite containing the UI * * @return the composite */ public Composite getComposite() { return composite; } /** * Transform process definition; * * @return */ public List<TransformProcess.Definition> getTransform() { return transform; } protected Control createExpressionTable(Composite parent) { setLayout(new MigLayout("insets 0", "[grow,fill][]", "[][][][][grow,fill][][][][grow,fill][][]")); Label label = new Label(this, SWT.LEFT); label.setText("Transform"); label.setLayoutData("cell 0 0 2 1,width pref!,left"); Button button = new Button(this, SWT.CENTER); button.setText("Add"); button.setLayoutData("cell 1 1 1 1,grow"); button.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { int row = table.getTable().getSelectionIndex(); Definition definition = new Definition(); definition.name = ""; definition.expression = Expression.NIL; transform.add(row, definition); table.refresh(); table.setSelection(new StructuredSelection(definition)); } }); button = new Button(this, SWT.CENTER); button.setText("Up"); button.setLayoutData("cell 1 2 1 1,grow"); button.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { int row = table.getTable().getSelectionIndex(); if (row == 0 || row == -1) { return; } row--; Definition definition = selectedDefinition(); transform.remove(definition); transform.add(row, definition); table.refresh(); table.setSelection(new StructuredSelection(definition)); } }); button = new Button(this, SWT.CENTER); button.setText("Down"); button.setLayoutData("cell 1 3 1 1,grow"); button.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { int row = table.getTable().getSelectionIndex(); if (row == transform.size() - 1 || row == -1) { return; } row++; Definition definition = selectedDefinition(); transform.remove(definition); transform.add(row, definition); table.refresh(); table.setSelection(new StructuredSelection(definition)); } }); button = new Button(this, SWT.CENTER); button.setText("Remove"); button.setLayoutData("cell 1 5 1 1,grow"); button.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { int row = table.getTable().getSelectionIndex(); if (row == -1) { return; } if (row > 0) { row = row - 1; } Definition definition = selectedDefinition(); transform.remove(definition); table.refresh(); if (row < transform.size()) { table.getTable().setSelection(row); } else { table.getTable().deselectAll(); } } }); table = new TableViewer(this, SWT.SINGLE | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); table.setContentProvider(ArrayContentProvider.getInstance()); table.getControl().setLayoutData("cell 0 1 1 5, grow, height 200:50%:70%,width 300:pref:100%"); TableViewerColumn column = new TableViewerColumn(table, SWT.NONE); column.getColumn().setWidth(100); column.getColumn().setMoveable(false); column.getColumn().setResizable(true); column.getColumn().setText("Attribute"); column.setLabelProvider(new ColumnLabelProvider() { @Override public String getText(Object element) { Definition definition = (Definition) element; return definition.name; } }); column = new TableViewerColumn(table, SWT.NONE); column.getColumn().setWidth(60); column.getColumn().setMoveable(false); column.getColumn().setResizable(true); column.getColumn().setText("Type"); column.getColumn().setAlignment(SWT.CENTER); column.setLabelProvider(new ColumnLabelProvider() { @Override public String getText(Object element) { Definition definition = (Definition) element; return definition.binding == null ? NO_CONTENT : definition.binding.getSimpleName(); } }); column = new TableViewerColumn(table, SWT.NONE); column.getColumn().setWidth(140); column.getColumn().setMoveable(false); column.getColumn().setResizable(true); column.getColumn().setText("Expression"); column.setLabelProvider(new ColumnLabelProvider() { @Override public String getText(Object element) { Definition definition = (Definition) element; return definition.expression == null ? NO_CONTENT : ECQL.toCQL(definition.expression); } }); table.getTable().setHeaderVisible(true); table.getTable().setLinesVisible(true); table.addSelectionChangedListener(tableListener); Transfer[] types = new Transfer[] { UDigByteAndLocalTransfer.getInstance() }; table.addDragSupport(DND.DROP_MOVE | DND.DROP_DEFAULT, types, new DragSourceAdapter() { @Override public void dragSetData(DragSourceEvent event) { IStructuredSelection selection = (IStructuredSelection) table.getSelection(); if (UDigByteAndLocalTransfer.getInstance().isSupportedType(event.dataType)) { event.data = selection.getFirstElement(); } } }); // drag drop order support table.addDropSupport(DND.DROP_MOVE | DND.DROP_DEFAULT, types, new ViewerDropAdapter(table) { @Override public boolean validateDrop(Object target, int operation, TransferData transferType) { if (target instanceof Definition) { return true; } else { return false; } } @Override public boolean performDrop(Object data) { if (data instanceof Definition) { listen(false); int index = transform.indexOf(getCurrentTarget()); // if (location == LOCATION_BEFORE) // index--; Definition definition = (Definition) data; transform.remove(definition); transform.add(index, definition); table.refresh(); table.setSelection(new StructuredSelection(definition)); listen(true); return true; } return false; } }); definitionLabel = new Label(this, SWT.LEFT); definitionLabel.setText("Definition"); definitionLabel.setLayoutData("cell 0 6 2 1, width pref!,left"); feedbackDecorator = new ControlDecoration(definitionLabel, SWT.RIGHT | SWT.TOP); name = new Text(this, SWT.SINGLE | SWT.BORDER); name.setEditable(true); name.setText(""); name.setLayoutData("cell 0 7 2 1"); expression = new ExpressionViewer(this, SWT.MULTI); // expression.setInput(expressionInput); expression.getControl().setLayoutData("cell 0 8 2 1,height 200:50%:50%,width 300:pref:100%"); expression.addSelectionChangedListener(expressionListener); // start up with nothing selected table.setSelection(StructuredSelection.EMPTY); enable(false); return this; } protected void listen(boolean listen) { if (listen) { name.addModifyListener(nameListener); expression.addSelectionChangedListener(expressionListener); } else { name.removeModifyListener(nameListener); expression.removeSelectionChangedListener(expressionListener); } } protected void enable(boolean isEditEnable) { definitionLabel.setEnabled(isEditEnable); name.setEnabled(isEditEnable); expression.getControl().setEnabled(isEditEnable); } protected Definition selectedDefinition() { ISelection selectedRow = table.getSelection(); if (!selectedRow.isEmpty() && selectedRow instanceof StructuredSelection) { StructuredSelection selection = (StructuredSelection) selectedRow; return (Definition) selection.getFirstElement(); } return null; // nothing to see here } }