Java tutorial
/* uDig - User Friendly Desktop Internet GIS client * http://udig.refractions.net * (C) 2004-2011, 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.tutorials.featureeditor; import java.math.BigDecimal; import net.refractions.udig.project.command.CompositeCommand; import net.refractions.udig.project.internal.commands.edit.SetEditFeatureCommand; import net.refractions.udig.project.internal.commands.edit.WriteEditFeatureCommand; import net.refractions.udig.project.ui.tool.IToolContext; import net.refractions.udig.tutorials.celleditor.FormComboBoxCellEditor; import net.refractions.udig.tutorials.celleditor.FormTextCellEditor; import org.eclipse.jface.action.Action; import org.eclipse.jface.viewers.ComboViewer; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CCombo; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; 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.eclipse.ui.forms.IMessage; import org.eclipse.ui.forms.IMessagePrefixProvider; import org.eclipse.ui.forms.events.ExpansionAdapter; import org.eclipse.ui.forms.events.ExpansionEvent; import org.eclipse.ui.forms.events.HyperlinkAdapter; import org.eclipse.ui.forms.events.HyperlinkEvent; import org.eclipse.ui.forms.widgets.ColumnLayout; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.eclipse.ui.forms.widgets.Section; import org.geotools.feature.simple.SimpleFeatureBuilder; import org.opengis.feature.IllegalAttributeException; import org.opengis.feature.simple.SimpleFeature; /** * A remake of the original 'Edit Feature' tutorial example with the ff changes: * <p> * <ul> * <li>use Eclipse Forms</li> * <li>use the natural earth "countries" dataset</li> * <li>use CellEditors for the form's fields</li> * </ul> * </p> * * @author Naz Chan */ public class CountryPanelFormCellEditor implements KeyListener, ISelectionChangedListener { /** Attribute name for attribute NAME_FORMA */ public final static String NAME_FORMA = "NAME_FORMA"; public final static String NAME_FORMA_LBL = "Name (formal)"; /** Attribute name for attribute NAME_SORT */ public final static String NAME_SORT = "NAME_SORT"; public final static String NAME_SORT_LBL = "Name (short)"; /** Attribute name for attribute POP_EST */ public final static String POP_EST = "POP_EST"; public final static String POP_EST_LBL = "Population Estimate"; /** Attribute name for attribute TYPE */ public final static String TYPE = "TYPE"; public final static String TYPE_LBL = "Status"; public final static String TYPE_SOV_LBL = "Sovereign Country"; public final static String TYPE_COU_LBL = "Country"; public final static String[] TYPE_OPTS = new String[] { TYPE_SOV_LBL, TYPE_COU_LBL }; /** Attribute name for attribute MAP_COLOR */ public final static String COLOR_MAP = "MAP_COLOR"; public final static String COLOR_MAP_LBL = "Map Color"; public final static Double[] COLOR_MAP_OPTS; static { COLOR_MAP_OPTS = new Double[13]; for (int i = 0; i < COLOR_MAP_OPTS.length; i++) { COLOR_MAP_OPTS[i] = Double.valueOf(Integer.toString(i + 1)); } } public final static String REMARKS_LBL = "Remarks"; /** * Used to construct UI */ private static final int MAX_COLS = 2; private static final int MIN_COLS = 1; private static final int LABEL_STYLE = SWT.SHADOW_IN; private static final int FIELD_STYLE = SWT.SHADOW_IN | SWT.BORDER; private static final int SECTION_STYLE = Section.TWISTIE | Section.TITLE_BAR | Section.DESCRIPTION | Section.EXPANDED; private FormToolkit toolkit; private ScrolledForm form; private Text nameSort; private Text nameFormal; private Text population; private CCombo type; private ComboViewer colorMap; private Action apply; private Action reset; /** * Used for editing the feature */ private SimpleFeature editedFeature; private SimpleFeature oldFeature; /** * Used send commands to the edit blackboard */ private IToolContext context; public void createControl(Composite parent, FormToolkit toolkit) { this.toolkit = toolkit; form = toolkit.createScrolledForm(parent); form.getForm().addMessageHyperlinkListener(new HyperlinkAdapter() { @Override public void linkActivated(HyperlinkEvent e) { final IMessage[] errors = (IMessage[]) e.data; if (errors.length > 0) { final IMessage topError = errors[0]; topError.getControl().setFocus(); } } }); form.getMessageManager().setMessagePrefixProvider(new IMessagePrefixProvider() { @Override public String getPrefix(Control control) { return control.getData().toString() + " - "; } }); form.setText("Country Form"); final ColumnLayout layout = new ColumnLayout(); layout.maxNumColumns = MAX_COLS; layout.minNumColumns = MIN_COLS; form.getBody().setLayout(layout); toolkit.decorateFormHeading(form.getForm()); final Section section = toolkit.createSection(form.getBody(), SECTION_STYLE); section.setText("Country Details"); section.setDescription("Update country details below."); section.addExpansionListener(new ExpansionAdapter() { public void expansionStateChanged(ExpansionEvent e) { // Nothing } }); final Composite client = toolkit.createComposite(section, SWT.NONE); GridLayout sectionLayout = new GridLayout(); sectionLayout.numColumns = 4; client.setLayout(sectionLayout); section.setClient(client); // SWT Widgets Label label = toolkit.createLabel(client, NAME_FORMA_LBL, LABEL_STYLE); FormTextCellEditor nameFormalEditor = new FormTextCellEditor(client, form.getMessageManager()); nameFormal = (Text) nameFormalEditor.getControl(); nameFormal.setData(NAME_FORMA_LBL); nameFormal.addKeyListener(this); GridData layoutData = new GridData(GridData.FILL_HORIZONTAL); layoutData.horizontalSpan = 3; nameFormal.setLayoutData(layoutData); label = toolkit.createLabel(client, NAME_SORT_LBL, LABEL_STYLE); FormTextCellEditor nameSortEditor = new FormTextCellEditor(client, form.getMessageManager()); nameSort = (Text) nameSortEditor.getControl(); nameSort.setData(NAME_SORT_LBL); nameSort.addKeyListener(this); layoutData = new GridData(GridData.FILL_HORIZONTAL); layoutData.horizontalSpan = 3; nameSort.setLayoutData(layoutData); label = toolkit.createLabel(client, POP_EST_LBL, LABEL_STYLE); FormTextCellEditor populationEditor = new FormTextCellEditor(client, form.getMessageManager()); population = (Text) populationEditor.getControl(); population.setData(POP_EST_LBL); population.addKeyListener(this); layoutData = new GridData(GridData.FILL_HORIZONTAL); layoutData.horizontalSpan = 3; population.setLayoutData(layoutData); label = toolkit.createLabel(client, TYPE_LBL, LABEL_STYLE); FormComboBoxCellEditor typeEditor = new FormComboBoxCellEditor(client, TYPE_OPTS, form.getMessageManager()); type = (CCombo) typeEditor.getControl(); type.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { setEnabled(true); } }); layoutData = new GridData(); layoutData.horizontalSpan = 3; type.setLayoutData(layoutData); // JFace Viewer label = toolkit.createLabel(client, COLOR_MAP_LBL, LABEL_STYLE); FormComboBoxCellEditor colorEditor = new FormComboBoxCellEditor(client, new String[] {}, form.getMessageManager()); CCombo colorCombo = (CCombo) colorEditor.getControl(); colorMap = new ComboViewer(colorCombo); colorMap.addSelectionChangedListener(this); layoutData = new GridData(); layoutData.horizontalSpan = 3; colorMap.getControl().setLayoutData(layoutData); // hook up to data colorMap.setContentProvider(new IStructuredContentProvider() { public Object[] getElements(Object inputElement) { if (inputElement instanceof Object[]) { return (Object[]) inputElement; } return null; } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { // For dynamic content we would register listeners here } public void dispose() { // Nothing } }); colorMap.setLabelProvider(new LabelProvider() { public String getText(Object element) { return " " + element + " color"; } }); colorMap.setInput(COLOR_MAP_OPTS); // Other sample section - to try out ColumnLayout final Section sectionOther = toolkit.createSection(form.getBody(), SECTION_STYLE); sectionOther.setText("Others"); sectionOther.setDescription( "Sample section to demo ColumnLayout, make the view width smaller to force it to relayout."); sectionOther.addExpansionListener(new ExpansionAdapter() { public void expansionStateChanged(ExpansionEvent e) { // Nothing } }); final Composite clientOther = toolkit.createComposite(sectionOther, SWT.NONE); sectionLayout = new GridLayout(); sectionLayout.numColumns = 4; clientOther.setLayout(sectionLayout); sectionOther.setClient(clientOther); Label remarksLbl = toolkit.createLabel(clientOther, REMARKS_LBL, LABEL_STYLE); FormTextCellEditor remarksEditor = new FormTextCellEditor(clientOther, form.getMessageManager()); Text remarks = (Text) remarksEditor.getControl(); remarks.setData(REMARKS_LBL); remarks.addKeyListener(this); layoutData = new GridData(GridData.FILL_HORIZONTAL); layoutData.horizontalSpan = 3; remarks.setLayoutData(layoutData); // Buttons apply = new Action("Apply") { @Override public void run() { applyChanges(); } }; apply.setEnabled(false); form.getToolBarManager().add(apply); reset = new Action("Reset") { @Override public void run() { resetChanges(); } }; reset.setEnabled(false); form.getToolBarManager().add(reset); form.getToolBarManager().update(true); } public void setFocus() { nameFormal.setFocus(); } private void setEnabled(boolean enabled) { if (oldFeature == null && enabled) { return; } apply.setEnabled(enabled); reset.setEnabled(enabled); } @Override public void selectionChanged(SelectionChangedEvent event) { setEnabled(true); } @Override public void keyPressed(KeyEvent e) { // Nothing } @Override public void keyReleased(KeyEvent e) { setEnabled(true); } public void setEditFeature(SimpleFeature newFeature, IToolContext newcontext) { this.context = newcontext; oldFeature = newFeature; if (oldFeature != null) { try { editedFeature = SimpleFeatureBuilder.copy(newFeature); } catch (IllegalAttributeException e) { // shouldn't happen } } else { editedFeature = null; } if (oldFeature == null) { nameSort.setText(""); colorMap.setSelection(new StructuredSelection()); nameFormal.setText(""); } else { // Set UI value for NAME_FORMA String nameFormalVal = (String) oldFeature.getAttribute(NAME_FORMA); if (nameFormalVal == null) nameFormalVal = ""; nameFormal.setText(nameFormalVal); // Set UI value for NAME_SORT String nameSortStr = (String) oldFeature.getAttribute(NAME_SORT); if (nameSortStr == null) nameSortStr = ""; nameSort.setText(nameSortStr); // Set UI value for POP_EST BigDecimal popEst = new BigDecimal((Double) oldFeature.getAttribute(POP_EST)); population.setText(popEst.toString()); // Set UI value for TYPE String typeStr = (String) oldFeature.getAttribute(TYPE); int selectedIndex = 0; if (TYPE_COU_LBL.equalsIgnoreCase(typeStr)) { selectedIndex = 1; } type.select(selectedIndex); // Set UI value for COLOR_MAP Double colorText = (Double) oldFeature.getAttribute(COLOR_MAP); if (colorText != null) { colorMap.setSelection(new StructuredSelection(colorText)); } else { colorMap.setSelection(new StructuredSelection()); } } setEnabled(false); } private void resetChanges() { setEditFeature(oldFeature, context); setEnabled(false); form.getMessageManager().removeAllMessages(); } private void applyChanges() { if (!verifyChanges()) { try { // Set feature value for NAME_FORMA editedFeature.setAttribute(NAME_FORMA, nameFormal.getText()); // Set feature value for NAME_SORT editedFeature.setAttribute(NAME_SORT, nameSort.getText()); // Set feature value for POP_EST editedFeature.setAttribute(POP_EST, Double.valueOf(population.getText())); // Set feature value for TYPE editedFeature.setAttribute(TYPE, (type.getSelectionIndex() == 0) ? TYPE_SOV_LBL : TYPE_COU_LBL); // Set feature value for COLOR_MAP StructuredSelection colorSelection = (StructuredSelection) colorMap.getSelection(); editedFeature.setAttribute(COLOR_MAP, colorSelection.getFirstElement()); } catch (IllegalAttributeException e1) { // shouldn't happen. } final CompositeCommand compComm = new CompositeCommand(); //Sets the feature (with the edited values) used in the view as the editFeature compComm.getCommands().add(new SetEditFeatureCommand(editedFeature)); //Write the changes to the actual dataset compComm.getCommands().add(new WriteEditFeatureCommand()); context.sendASyncCommand(compComm); setEnabled(false); } } private boolean verifyChanges() { boolean hasError = false; if (!isValid(nameFormal)) { hasError = true; } if (!isValid(nameSort)) { hasError = true; } if (!(isValid(population) && isNumber(population))) { hasError = true; } return hasError; } private boolean isValid(Text text) { if (editedFeature != null) { form.getMessageManager().removeMessages(text); if (text.getText() == null || "".equals(text.getText())) { form.getMessageManager().addMessage(text, "Must not be blank.", null, IMessage.ERROR, text); return false; } } return true; } private boolean isNumber(Text text) { if (editedFeature != null) { try { Double.valueOf(text.getText()); } catch (NumberFormatException e) { form.getMessageManager().addMessage(text, "Must be a number.", null, IMessage.ERROR, text); return false; } } return true; } }