Package org.locationtech.udig.feature.editor.field

Source Code of org.locationtech.udig.feature.editor.field.StringAttributeField

/* uDig - User Friendly Desktop Internet GIS client
* http://udig.refractions.net
* (C) 2004-2010, Refractions Research Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD
* License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).
*/
package org.locationtech.udig.feature.editor.field;

import org.locationtech.udig.internal.ui.SendLogDialog;
import org.locationtech.udig.project.ui.feature.EditFeature;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.geotools.feature.FeatureTypes;
import org.geotools.feature.type.Types;
import org.geotools.util.Converters;
import org.opengis.feature.IllegalAttributeException;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;

/**
* Attribute field for a string type attribute.
*
* @since 1.2.0
*/
public class StringAttributeField extends AttributeField {

    /**
     * Validation strategy constant (value <code>0</code>) indicating that the editor should perform
     * validation after every key stroke.
     *
     * @see #setValidateStrategy
     */
    public static final int VALIDATE_ON_KEY_STROKE = 0;

    /**
     * Validation strategy constant (value <code>1</code>) indicating that the editor should perform
     * validation only when the text widget loses focus.
     *
     * @see #setValidateStrategy
     */
    public static final int VALIDATE_ON_FOCUS_LOST = 1;

    /**
     * Text limit constant (value <code>-1</code>) indicating unlimited text limit and width.
     */
    public static int UNLIMITED = -1;

    /**
     * Cached valid state.
     */
    protected boolean isValid;

    /**
     * Old text value.
     *
     * @since 3.4 this field is protected.
     */
    protected String oldValue;

    /**
     * The text field, or <code>null</code> if none.
     */
    protected Text textField;

    /**
     * Width of text field in characters; initially unlimited.
     */
    private int widthInChars = UNLIMITED;

    /**
     * Text limit of text field in characters; initially unlimited.
     */
    protected int textLimit = UNLIMITED;

    /**
     * Text field is single line or multi, we need to know if it's single line <code>false</code> by
     * default
     */
    protected boolean multi = false;

    /**
     * The error message, or <code>null</code> if none.
     */
    private String errorMessage;

    /**
     * Indicates whether the empty string is legal; <code>true</code> by default.
     */
    private boolean emptyStringAllowed = true;

    /**
     * The validation strategy; <code>VALIDATE_ON_KEY_STROKE</code> by default.
     */
    private int validateStrategy = VALIDATE_ON_KEY_STROKE;

    private boolean required;

    /**
     * Creates a new string field editor
     */
    protected StringAttributeField() {
    }

    /**
     * Creates a string field editor. Use the method <code>setTextLimit</code> to limit the text.
     *
     * @param name the name of the preference this field editor works on
     * @param labelText the label text of the field editor
     * @param width the width of the text input field in characters, or <code>UNLIMITED</code> for
     *        no limit
     * @param strategy either <code>VALIDATE_ON_KEY_STROKE</code> to perform on the fly checking
     *        (the default), or <code>VALIDATE_ON_FOCUS_LOST</code> to perform validation only after
     *        the text has been typed in
     * @param parent the parent of the field editor's control
     * @since 2.0
     */
    public StringAttributeField( String name, String labelText, int width, int strategy,
            Composite parent, int control_style) {
        if (control_style == 1) {
            multi = true;
        }
        init(name, labelText);
        widthInChars = width;
        setValidateStrategy(strategy);
        isValid = false;
        errorMessage = "Text not valid";
        createControl(parent);
    }

    /**
     * Creates a string field editor. Use the method <code>setTextLimit</code> to limit the text.
     *
     * @param name the name of the preference this field editor works on
     * @param labelText the label text of the field editor
     * @param width the width of the text input field in characters, or <code>UNLIMITED</code> for
     *        no limit
     * @param parent the parent of the field editor's control
     */
    public StringAttributeField( String name, String labelText, int width, Composite parent,
            int control_style ) {
        this(name, labelText, width, VALIDATE_ON_KEY_STROKE, parent, control_style);
    }

    /**
     * Creates a string field editor of unlimited width. Use the method <code>setTextLimit</code> to
     * limit the text.
     *
     * @param name the name of the preference this field editor works on
     * @param labelText the label text of the field editor
     * @param parent the parent of the field editor's control
     */

    public StringAttributeField( String name, String labelText, Composite parent, int control_style ) {
        this(name, labelText, UNLIMITED, control_style, parent, control_style); // UNLIMITED
    }

    public StringAttributeField( String name, String labelText, Composite parent ) {
        this(name, labelText, UNLIMITED, parent, 0); // UNLIMITED
    }

    /**
     * Creates a string field editor of unlimited width. Use the method <code>setTextLimit</code> to
     * limit the text.
     *
     * @param name the name of the preference this field editor works on
     * @param labelText the label text of the field editor
     * @param parent the parent of the field editor's control
     * @param line text field type. True if multiline, false if single line
     */

    /*
     * (non-Javadoc) Method declared on AttributeField.
     */
    public void adjustForNumColumns( int numColumns ) {
        GridData gd = (GridData) textField.getLayoutData();
        gd.horizontalSpan = numColumns - 1;
        // We only grab excess space if we have to
        // If another field editor has more columns then
        // we assume it is setting the width.
        gd.grabExcessHorizontalSpace = gd.horizontalSpan == 1;
    }

    /**
     * Checks whether the text input field contains a valid value or not.
     *
     * @return <code>true</code> if the field value is valid, and <code>false</code> if invalid
     */
    public boolean checkState() {
        boolean result = false;
        if (emptyStringAllowed) {
            result = true;
        }

        if (textField == null) {
            result = false;
        }

        String txt = textField.getText();

        result = (txt.trim().length() > 0) || emptyStringAllowed;

        // call hook for subclasses
        result = result && doCheckState();

        if (result) {
            clearErrorMessage();
        } else {
            showErrorMessage(errorMessage);
        }

        return result;
    }

    /**
     * Hook for subclasses to do specific state checks.
     * <p>
     * The default implementation of this framework method does nothing and returns
     * <code>true</code>. Subclasses should override this method to specific state checks.
     * </p>
     *
     * @return <code>true</code> if the field value is valid, and <code>false</code> if invalid
     */
    protected boolean doCheckState() {
        EditFeature feature = getFeature();
        if (feature == null)
            return true; // cannot check right now
        SimpleFeatureType schema = feature.getFeatureType();
        AttributeDescriptor descriptor = schema.getDescriptor(getAttributeName());
        if (descriptor == null) {
            // the schema changed on us! help ...
            return false;
        }
        String text = textField.getText();

        if (text == null || text.length() == 0) {
            return !descriptor.isNillable();
        }
        Object value = Converters.convert(text, descriptor.getType().getBinding());
        try {
            Types.validate(descriptor, value);
            if( isRequired() && value == null ){
                errorMessage = getAttributeName() + " is required";
                showErrorMessage(errorMessage);
                return false;
            }
            return true;
        } catch (IllegalAttributeException bad) {
            errorMessage = bad.getLocalizedMessage();
            return false;
        }
    }

    boolean isRequired(){
        return required;
    }
   
    public void setRequired( boolean required ) {
        this.required = required;
    }
    /**
     * Fills this field editor's basic controls into the given parent.
     * <p>
     * The string field implementation of this <code>AttributeField</code> framework method
     * contributes the text field. Subclasses may override but must call
     * <code>super.doFillIntoGrid</code>.
     * </p>
     */
    protected void doFillIntoGrid( final Composite parent, int numColumns ) {
        Label label = getLabelControl(parent);
        GridData gd = new GridData();
        gd.horizontalSpan = 1;
        label.setLayoutData(gd);

        textField = getTextControl(parent);
        gd = new GridData();
        gd.horizontalIndent = 5;
        gd.horizontalSpan = numColumns - 1;
        if (widthInChars != UNLIMITED) {
            GC gc = new GC(textField);
            try {
                Point extent = gc.textExtent("X");//$NON-NLS-1$
                gd.widthHint = widthInChars * extent.x;
            } finally {
                gc.dispose();
            }
        } else {
            gd.horizontalAlignment = GridData.FILL;
            gd.grabExcessHorizontalSpace = true;
        }
        if (multi) {
          //  System.out.println("Multi is true");
            // gd.grabExcessVerticalSpace = true;
            GC gc = new GC(textField);
            try {
                Point extent = gc.textExtent("X");//$NON-NLS-1$
                gd.heightHint = extent.y * 3;
            } finally {
                gc.dispose();
            }
        }
        textField.setLayoutData(gd);
        if (multi) {
            textField.addKeyListener(new KeyAdapter(){
                @Override
                public void keyReleased( KeyEvent e ) {
                    int numLines = textField.getLineCount();
                    GridData gd = (GridData) textField.getLayoutData();
                    GC gc = new GC(textField);
                    Point extent = gc.textExtent("X");//$NON-NLS-1$
                    if (numLines >= 3) {
                        if ((gd.heightHint / extent.y) > (numLines + 1)) {
                            try {
                                gd.heightHint = extent.y * (numLines--);
                            } finally {
                                gc.dispose();
                            }

                        } else {
                            try {
                                gd.heightHint = extent.y * (numLines++);
                            } finally {
                                gc.dispose();
                            }

                        }

                    }
                    else{
                        try {
                            gd.heightHint = extent.y * 3;
                        } finally {
                            gc.dispose();
                        }
                    }

                    parent.layout();
                }
            });
        }

    }

    /*
     * (non-Javadoc) Method declared on AttributeField.
     */
    public void doLoad() {
        if (textField != null && getFeature() != null) {
            // AttributeDescriptor descriptor = getFeature().getType().getDescriptor(
            // getAttributeName() );
            // int length = FeatureTypes.getFieldLength(descriptor);

            Object value = getFeature().getAttribute(getAttributeName());
            String text = Converters.convert(value, String.class);
            if (text == null) {
                text = "";
            }
            textField.setText(text);
            oldValue = text;
        }
    }

    /*
     * (non-Javadoc) Method declared on AttributeField.
     */
    protected void doLoadDefault() {
        if (textField != null) {
            SimpleFeatureType schema = getFeature().getFeatureType();
            AttributeDescriptor descriptor = schema.getDescriptor(getAttributeName());
            Object value = descriptor.getDefaultValue();

            String text = Converters.convert(value, String.class);
            textField.setText(text);
        }
        valueChanged();
    }

    /*
     * (non-Javadoc) Method declared on AttributeField.
     */
    protected void doStore() {
        SimpleFeatureType schema = getFeature().getFeatureType();
        AttributeDescriptor descriptor = schema.getDescriptor(getAttributeName());

        String text = textField.getText();
        Object value = Converters.convert(text, descriptor.getType().getBinding());
        getFeature().setAttribute(getAttributeName(), value);
    }

    /**
     * Returns the error message that will be displayed when and if an error occurs.
     *
     * @return the error message, or <code>null</code> if none
     */
    public String getErrorMessage() {
        return errorMessage;
    }

    /*
     * (non-Javadoc) Method declared on AttributeField.
     */
    public int getNumberOfControls() {
        return 2;
    }

    /**
     * Returns the field editor's value.
     *
     * @return the current value
     */
    public String getStringValue() {
        if (textField != null) {
            return textField.getText();
        }

        Object value = getFeature().getAttribute(getAttributeName());
        String text = Converters.convert(value, String.class);
        return text;
    }

    /**
     * Returns this field editor's text control.
     *
     * @return the text control, or <code>null</code> if no text field is created yet
     */
    protected Text getTextControl() {
        return textField;
    }

    public Text getControl() {
        return textField;
    }

    /**
     * Returns this field editor's text control.
     * <p>
     * The control is created if it does not yet exist
     * </p>
     *
     * @param parent the parent
     * @return the text control
     */
    public Text getTextControl( Composite parent ) {
        if (textField == null) {
            if (multi) {
                textField = new Text(parent, SWT.MULTI | SWT.BORDER); // this is a multi-line text
                // field
            } else {
                textField = new Text(parent, SWT.SINGLE | SWT.BORDER); // this is a single-line text
                // field
            }
           
            textField.setFont(parent.getFont());
            switch( validateStrategy ) {
            case VALIDATE_ON_KEY_STROKE:
                textField.addKeyListener(new KeyAdapter(){

                    /*
                     * (non-Javadoc)
                     * @see
                     * org.eclipse.swt.events.KeyAdapter#keyReleased(org.eclipse.swt.events.KeyEvent
                     * )
                     */
                    public void keyReleased( KeyEvent e ) {
                        valueChanged();
                    }
                });
                textField.addFocusListener(new FocusAdapter(){
                    // Ensure that the value is checked on focus loss in case we
                    // missed a keyRelease or user hasn't released key.
                    // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=214716
                    public void focusLost( FocusEvent e ) {
                        valueChanged();
                    }
                });

                break;
            case VALIDATE_ON_FOCUS_LOST:
                textField.addKeyListener(new KeyAdapter(){
                    public void keyPressed( KeyEvent e ) {
                        clearErrorMessage();
                    }
                });
                textField.addFocusListener(new FocusAdapter(){
                    public void focusGained( FocusEvent e ) {
                        refreshValidState();
                    }

                    public void focusLost( FocusEvent e ) {
                        valueChanged();
                        clearErrorMessage();
                    }
                });
                break;
            default:
                Assert.isTrue(false, "Unknown validate strategy");//$NON-NLS-1$
            }
            textField.addDisposeListener(new DisposeListener(){
                public void widgetDisposed( DisposeEvent event ) {
                    textField = null;
                }
            });
            if (textLimit > 0) {// Only set limits above 0 - see SWT spec
                textField.setTextLimit(textLimit);
            }
        } else {
            checkParent(textField, parent);
        }
        return textField;
    }

    /**
     * Returns whether an empty string is a valid value.
     *
     * @return <code>true</code> if an empty string is a valid value, and <code>false</code> if an
     *         empty string is invalid
     * @see #setEmptyStringAllowed
     */
    public boolean isEmptyStringAllowed() {
        return emptyStringAllowed;
    }

    /*
     * (non-Javadoc) Method declared on AttributeField.
     */
    public boolean isValid() {
        return isValid;
    }

    /*
     * (non-Javadoc) Method declared on AttributeField.
     */
    protected void refreshValidState() {
        isValid = checkState();
    }

    /**
     * Sets whether the empty string is a valid value or not.
     *
     * @param b <code>true</code> if the empty string is allowed, and <code>false</code> if it is
     *        considered invalid
     */
    public void setEmptyStringAllowed( boolean b ) {
        emptyStringAllowed = b;
    }

    /**
     * Sets the error message that will be displayed when and if an error occurs.
     *
     * @param message the error message
     */
    public void setErrorMessage( String message ) {
        errorMessage = message;
    }

    /*
     * (non-Javadoc) Method declared on AttributeField.
     */
    public void setFocus() {
        if (textField != null) {
            textField.setFocus();
        }
    }

    /**
     * Sets this field editor's value.
     *
     * @param value the new value, or <code>null</code> meaning the empty string
     */
    public void setStringValue( String value ) {
        if (textField != null) {
            if (value == null) {
                value = "";//$NON-NLS-1$
            }
            oldValue = textField.getText();
            if (!oldValue.equals(value)) {
                textField.setText(value);
                valueChanged();
            }
        }
    }

    /**
     * Sets this text field's text limit.
     *
     * @param limit the limit on the number of character in the text input field, or
     *        <code>UNLIMITED</code> for no limit
     */
    public void setTextLimit( int limit ) {
        textLimit = limit;
        if (textField != null) {
            textField.setTextLimit(limit);
        }
    }

    /**
     * Sets the strategy for validating the text.
     * <p>
     * Calling this method has no effect after <code>createPartControl</code> is called. Thus this
     * method is really only useful for subclasses to call in their constructor. However, it has
     * public visibility for backward compatibility.
     * </p>
     *
     * @param value either <code>VALIDATE_ON_KEY_STROKE</code> to perform on the fly checking (the
     *        default), or <code>VALIDATE_ON_FOCUS_LOST</code> to perform validation only after the
     *        text has been typed in
     */
    public void setValidateStrategy( int value ) {
        Assert.isTrue(value == VALIDATE_ON_FOCUS_LOST || value == VALIDATE_ON_KEY_STROKE);
        validateStrategy = value;
    }

    /**
     * Shows the error message set via <code>setErrorMessage</code>.
     */
    public void showErrorMessage() {
        showErrorMessage(errorMessage);
    }

    /**
     * Informs this field editor's listener, if it has one, about a change to the value (
     * <code>VALUE</code> property) provided that the old and new values are different.
     * <p>
     * This hook is <em>not</em> called when the text is initialized (or reset to the default value)
     * from the preference store.
     * </p>
     */
    protected void valueChanged() {
       
        setPresentsDefaultValue(false);
        boolean oldState = isValid;
        refreshValidState();
        if (isValid != oldState) {
            fireStateChanged(IS_VALID, oldState, isValid);
        }       
       
        textField.addFocusListener(new FocusAdapter(){
            public void focusGained( FocusEvent e ) {
                refreshValidState();
            }

            public void focusLost( FocusEvent e ) {
                String newValue = textField.getText();
                if (!newValue.equals(oldValue)) {
                    fireValueChanged(VALUE, oldValue, newValue);
                    oldValue = newValue;
                    System.out.println("oldValue");
               
                clearErrorMessage();
            }
        });


    }

    public void setVisible( boolean visible ) {
        super.setVisible(visible);
        if (getControl() != null && !getControl().isDisposed()) {
            getControl().setVisible(visible);
        }
    }

    /*
     * @see AttributeField.setEnabled(boolean,Composite).
     */
    public void setEnabled( boolean enabled ) {
        super.setEnabled(enabled);
        if (getControl() != null && !getControl().isDisposed()) {
            getControl().setEnabled(enabled);
        }
    }

}
TOP

Related Classes of org.locationtech.udig.feature.editor.field.StringAttributeField

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.