Package org.eclipse.sapphire.ui.forms.swt

Source Code of org.eclipse.sapphire.ui.forms.swt.TextFieldPropertyEditorPresentation

/******************************************************************************
* Copyright (c) 2014 Oracle, Accenture and Modelity Technologies
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*   Konstantin Komissarchik - initial implementation and ongoing maintenance
*   Kamesh Sampath - [354199] Support content proposals in text field property editor
*   Roded Bahat - [376198] Vertically align actions for @LongString property editors
******************************************************************************/

package org.eclipse.sapphire.ui.forms.swt;

import static org.eclipse.sapphire.ui.SapphireActionSystem.ACTION_ASSIST;
import static org.eclipse.sapphire.ui.SapphireActionSystem.ACTION_BROWSE;
import static org.eclipse.sapphire.ui.SapphireActionSystem.ACTION_JUMP;
import static org.eclipse.sapphire.ui.SapphireActionSystem.createFilterByActionId;
import static org.eclipse.sapphire.ui.forms.PropertyEditorPart.DATA_BINDING;
import static org.eclipse.sapphire.ui.forms.PropertyEditorPart.RELATED_CONTROLS;
import static org.eclipse.sapphire.ui.forms.swt.GridLayoutUtil.gd;
import static org.eclipse.sapphire.ui.forms.swt.GridLayoutUtil.gdfill;
import static org.eclipse.sapphire.ui.forms.swt.GridLayoutUtil.gdhfill;
import static org.eclipse.sapphire.ui.forms.swt.GridLayoutUtil.gdvalign;
import static org.eclipse.sapphire.ui.forms.swt.GridLayoutUtil.gdvfill;
import static org.eclipse.sapphire.ui.forms.swt.GridLayoutUtil.glayout;
import static org.eclipse.sapphire.ui.forms.swt.GridLayoutUtil.glspacing;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.eclipse.jface.bindings.keys.KeyStroke;
import org.eclipse.jface.bindings.keys.ParseException;
import org.eclipse.jface.fieldassist.ContentProposalAdapter;
import org.eclipse.jface.fieldassist.IContentProposal;
import org.eclipse.jface.fieldassist.IContentProposalProvider;
import org.eclipse.jface.fieldassist.TextContentAdapter;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.sapphire.Event;
import org.eclipse.sapphire.Listener;
import org.eclipse.sapphire.LoggingService;
import org.eclipse.sapphire.Sapphire;
import org.eclipse.sapphire.Serialization;
import org.eclipse.sapphire.Value;
import org.eclipse.sapphire.ValueProperty;
import org.eclipse.sapphire.modeling.annotations.LongString;
import org.eclipse.sapphire.modeling.annotations.SensitiveData;
import org.eclipse.sapphire.services.ContentProposal;
import org.eclipse.sapphire.services.ContentProposalService;
import org.eclipse.sapphire.ui.SapphireAction;
import org.eclipse.sapphire.ui.SapphireActionGroup;
import org.eclipse.sapphire.ui.SapphireActionHandler;
import org.eclipse.sapphire.ui.SapphireActionHandler.PostExecuteEvent;
import org.eclipse.sapphire.ui.SapphireActionHandlerFilter;
import org.eclipse.sapphire.ui.SapphirePart;
import org.eclipse.sapphire.ui.assist.internal.PropertyEditorAssistDecorator;
import org.eclipse.sapphire.ui.forms.FormComponentPart;
import org.eclipse.sapphire.ui.forms.PropertyEditorDef;
import org.eclipse.sapphire.ui.forms.PropertyEditorPart;
import org.eclipse.sapphire.ui.forms.swt.internal.TextFieldBinding;
import org.eclipse.sapphire.ui.forms.swt.internal.TextOverlayPainter;
import org.eclipse.sapphire.ui.listeners.ValuePropertyEditorListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;

/**
* @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a>
* @author <a href="mailto:kamesh.sampath@accenture.com">Kamesh Sampath</a>
* @author <a href="mailto:rodedb@gmail.com">Roded Bahat</a>
*/

public class TextFieldPropertyEditorPresentation extends ValuePropertyEditorPresentation
{
    private Text textField;
   
    private static final String CONTENT_ASSIST_KEY_STROKE_STRING = "Ctrl+Space";
    private static final KeyStroke CONTENT_ASSIST_KEY_STROKE;
   
    static
    {
        KeyStroke keyStroke = null;
       
        try
        {
            keyStroke = KeyStroke.getInstance( CONTENT_ASSIST_KEY_STROKE_STRING );
        }
        catch( ParseException e )
        {
            Sapphire.service( LoggingService.class ).log( e );
        }
       
        CONTENT_ASSIST_KEY_STROKE = keyStroke;
    }

    public TextFieldPropertyEditorPresentation( final FormComponentPart part, final SwtPresentation parent, final Composite composite )
    {
        super( part, parent, composite );
    }

    @Override
    protected void createContents( final Composite parent )
    {
        createContents( parent, false );
    }
   
    protected Control createContents( final Composite parent,
                                      final boolean suppressBrowseAction )
    {
        final PropertyEditorPart part = part();
        final Value<?> property = (Value<?>) part.property();
       
        final boolean isLongString = property.definition().hasAnnotation( LongString.class );
        final boolean isDeprecated = property.definition().hasAnnotation( Deprecated.class );
        final boolean isReadOnly = ( property.definition().isReadOnly() || part.getRenderingHint( PropertyEditorDef.HINT_READ_ONLY, false ) );
        final boolean isSensitiveData = property.definition().hasAnnotation( SensitiveData.class );
       
        final SapphireActionGroup actions = getActions();
        final SapphireActionHandler jumpActionHandler = actions.getAction( ACTION_JUMP ).getFirstActiveHandler();

        final SapphireToolBarActionPresentation toolBarActionsPresentation = new SapphireToolBarActionPresentation( getActionPresentationManager() );
        toolBarActionsPresentation.addFilter( createFilterByActionId( ACTION_ASSIST ) );
        toolBarActionsPresentation.addFilter( createFilterByActionId( ACTION_JUMP ) );
       
        actions.addFilter
        (
            new SapphireActionHandlerFilter()
            {
                @Override
                public boolean check( final SapphireActionHandler handler )
                {
                    final String actionId = handler.getAction().getId();
                   
                    if( actionId.equals( ACTION_BROWSE ) && ( isReadOnly || suppressBrowseAction ) )
                    {
                        return false;
                    }
                   
                    return true;
                }
            }
        );
       
        final boolean isActionsToolBarNeeded = toolBarActionsPresentation.hasActions();
        final boolean isBrowseOnly = part.getRenderingHint( PropertyEditorDef.HINT_BROWSE_ONLY, false );
       
        final Composite textFieldParent = createMainComposite
        (
            parent,
            new CreateMainCompositeDelegate( part )
            {
                @Override
                public boolean canScaleVertically()
                {
                    return isLongString;
                }
            }
        );
       
        addControl( textFieldParent );

        int textFieldParentColumns = 1;
        if( isActionsToolBarNeeded ) textFieldParentColumns++;
        if( isDeprecated ) textFieldParentColumns++;
       
        textFieldParent.setLayout( glayout( textFieldParentColumns, 0, 0, 0, 0 ) );
       
        final Composite nestedComposite = new Composite( textFieldParent, SWT.NONE );
        nestedComposite.setLayoutData( isLongString ? gdfill() : gdvalign( gdhfill(), SWT.CENTER ) );
        nestedComposite.setLayout( glspacing( glayout( 2, 0, 0 ), 2 ) );
       
        addControl( nestedComposite );
       
        final PropertyEditorAssistDecorator decorator = createDecorator( nestedComposite );
       
        decorator.control().setLayoutData( gdvalign( gd(), SWT.TOP ) );
        decorator.addEditorControl( nestedComposite );
       
        final int style
            = SWT.BORDER |
              ( isLongString ? SWT.MULTI | SWT.WRAP | SWT.V_SCROLL : SWT.NONE ) |
              ( ( isReadOnly || isBrowseOnly ) ? SWT.READ_ONLY : SWT.NONE ) |
              ( isSensitiveData ? SWT.PASSWORD : SWT.NONE );
       
        this.textField = new Text( nestedComposite, style );
        this.textField.setLayoutData( gdfill() );
        decorator.addEditorControl( this.textField, true );
       
        final Serialization serialization = property.definition().getAnnotation( Serialization.class );

        final TextOverlayPainter.Controller textOverlayPainterController = new TextOverlayPainter.Controller()
        {
            @Override
            public boolean isHyperlinkEnabled()
            {
                return ( jumpActionHandler == null ? false : jumpActionHandler.isEnabled() );
            }

            @Override
            public void handleHyperlinkEvent()
            {
                if( jumpActionHandler != null )
                {
                    jumpActionHandler.execute( TextFieldPropertyEditorPresentation.this );
                }
            }

            @Override
            public String overlay()
            {
                String def = property.disposed() ? null : property.getDefaultText();
               
                if( def != null && isSensitiveData )
                {
                    final StringBuilder buf = new StringBuilder();
                   
                    for( int i = 0, n = def.length(); i < n; i++ )
                    {
                        buf.append( "\u25CF" );
                    }
                   
                    def = buf.toString();
                }
               
                if( def == null && serialization != null )
                {
                    def = serialization.primary();
                }
               
                return def;
            }
        };
           
        TextOverlayPainter.install( this.textField, textOverlayPainterController );
       
        if( isBrowseOnly || isReadOnly )
        {
            final Color bgcolor = new Color( this.textField.getDisplay(), 245, 245, 245 );
            this.textField.setBackground( bgcolor );
           
            this.textField.addDisposeListener
            (
                new DisposeListener()
                {
                    public void widgetDisposed( final DisposeEvent event )
                    {
                        bgcolor.dispose();
                    }
                }
            );
        }
       
        final List<Control> relatedControls = new ArrayList<Control>();
        this.textField.setData( RELATED_CONTROLS, relatedControls );
       
        final Listener actionHandlerListener = new Listener()
        {
            @Override
            public void handle( final Event event )
            {
                if( event instanceof PostExecuteEvent )
                {
                    if( ! TextFieldPropertyEditorPresentation.this.textField.isDisposed() )
                    {
                        TextFieldPropertyEditorPresentation.this.textField.setFocus();
                        TextFieldPropertyEditorPresentation.this.textField.setSelection( 0, TextFieldPropertyEditorPresentation.this.textField.getText().length() );
                    }
                }
            }
        };
       
        for( SapphireAction action : actions.getActions() )
        {
            if( ! action.getId().equals( ACTION_ASSIST ) )
            {
                for( SapphireActionHandler handler : action.getActiveHandlers() )
                {
                    handler.attach( actionHandlerListener );
                }
            }
        }
       
        if( isActionsToolBarNeeded )
        {
            final int alignment = ( isLongString ? SWT.VERTICAL : SWT.HORIZONTAL );
            final ToolBar toolbar = new ToolBar( textFieldParent, SWT.FLAT | alignment );
            toolbar.setLayoutData( gdvfill() );
            toolBarActionsPresentation.setToolBar( toolbar );
            toolBarActionsPresentation.render();
            addControl( toolbar );
            decorator.addEditorControl( toolbar );
            relatedControls.add( toolbar );
        }
       
        final ContentProposalService contentProposalService = property.service( ContentProposalService.class );
       
        if( contentProposalService != null )
        {
            final ContentProposalProvider contentProposalProvider = new ContentProposalProvider( contentProposalService, part );
           
            final ContentProposalAdapter contentProposalAdapter
                = new ContentProposalAdapter( this.textField, new TextContentAdapter(), contentProposalProvider, CONTENT_ASSIST_KEY_STROKE, null );
           
            contentProposalAdapter.setPropagateKeys( true );
            contentProposalAdapter.setLabelProvider( new ContentProposalLabelProvider() );
            contentProposalAdapter.setProposalAcceptanceStyle( ContentProposalAdapter.PROPOSAL_REPLACE );
        }
       
        if( isDeprecated )
        {
            final Control deprecationMarker = createDeprecationMarker( textFieldParent );
            deprecationMarker.setLayoutData( gd() );
        }
       
        this.binding = new TextFieldBinding( this, this.textField );

        this.textField.setData( DATA_BINDING, this.binding );
       
        addControl( this.textField );
       
        // Hookup property editor listeners.
       
        final List<Class<?>> listenerClasses
            = part.getRenderingHint( PropertyEditorDef.HINT_LISTENERS, Collections.<Class<?>>emptyList() );
       
        if( ! listenerClasses.isEmpty() )
        {
            final List<ValuePropertyEditorListener> listeners = new ArrayList<ValuePropertyEditorListener>();
           
            for( Class<?> cl : listenerClasses )
            {
                try
                {
                    final ValuePropertyEditorListener listener = (ValuePropertyEditorListener) cl.newInstance();
                    listener.initialize( this );
                    listeners.add( listener );
                }
                catch( Exception e )
                {
                    Sapphire.service( LoggingService.class ).log( e );
                }
            }
           
            if( ! listeners.isEmpty() )
            {
                this.textField.addModifyListener
                (
                    new ModifyListener()
                    {
                        public void modifyText( final ModifyEvent event )
                        {
                            for( ValuePropertyEditorListener listener : listeners )
                            {
                                try
                                {
                                    listener.handleValueChanged();
                                }
                                catch( Exception e )
                                {
                                    Sapphire.service( LoggingService.class ).log( e );
                                }
                            }
                        }
                    }
                );
            }
        }

        return this.textField;
    }

    @Override
    protected boolean canScaleVertically()
    {
        return property().definition().hasAnnotation( LongString.class );
    }
   
    @Override
    protected void handleFocusReceivedEvent()
    {
        this.textField.setFocus();
    }

    public static final class Factory extends PropertyEditorPresentationFactory
    {
        @Override
        public PropertyEditorPresentation create( final PropertyEditorPart part, final SwtPresentation parent, final Composite composite )
        {
            if( part.property().definition() instanceof ValueProperty )
            {
                return new TextFieldPropertyEditorPresentation( part, parent, composite );
            }
           
            return null;
        }
    }
   
    private static final class ContentProposalProvider implements
            IContentProposalProvider {
        private ContentProposalService contentProposalService;

        private ContentProposalService.Session session = null;
        private SapphirePart sapphirePart;

        public ContentProposalProvider(
                ContentProposalService contentProposalService,
                SapphirePart sapphirePart) {
            this.contentProposalService = contentProposalService;
            this.sapphirePart = sapphirePart;
        }

        public IContentProposal[] getProposals(String contents, int position) {
            if (this.session == null) {
                this.session = this.contentProposalService.session();
            }

            final String oldFilter = this.session.filter();
            final int oldFilterLength = oldFilter.length();
            final String newFilter = contents.substring( 0, position );

            if( position < oldFilterLength || ! oldFilter.equals( newFilter ) )
            {
                this.session = this.contentProposalService.session();
               
                if( position > 0 )
                {
                    this.session.advance( newFilter );
                }
            }
            else if( position > oldFilterLength )
            {
                this.session.advance( newFilter.substring( oldFilterLength ) );
            }

            List<ContentProposal> filterProposals = this.session.proposals();
            IContentProposal[] arrContentProposals = makeProposalArray(filterProposals);
            return arrContentProposals;
        }

        private IContentProposal[] makeProposalArray(
                List<ContentProposal> proposals) {
            if (proposals != null) {
                IContentProposal[] arrContentProposals = new IContentProposal[proposals
                        .size()];
                for (int i = 0; i < proposals.size(); i++) {
                    ContentProposal contentProposalInfo = proposals.get(i);
                    ImageContentProposal contentProposal = new ImageContentProposal(
                            contentProposalInfo.content(),
                            contentProposalInfo.label(),
                            contentProposalInfo.description(),
                            contentProposalInfo.content().length(),
                            this.sapphirePart.getSwtResourceCache().image(
                                    contentProposalInfo.image()));
                    arrContentProposals[i] = contentProposal;
                }
                return arrContentProposals;
            } else {
                return new IContentProposal[0];
            }
        }
    }

    private static final class ContentProposalLabelProvider extends LabelProvider
    {
        @Override
        public Image getImage(Object element) {
   
            return ((ImageContentProposal) element).getImage();
        }
   
        @Override
        public String getText(Object element) {
            return ((ImageContentProposal) element).getLabel();
        }
    }

    private static final class ImageContentProposal extends org.eclipse.jface.fieldassist.ContentProposal {
   
        private Image image;
   
        public ImageContentProposal(String content, String label,
                String description, int cursorPosition, Image image) {
            super(content, label, description, cursorPosition);
            this.image = image;
        }
   
        public Image getImage() {
            return this.image;
        }
    }
   
}
TOP

Related Classes of org.eclipse.sapphire.ui.forms.swt.TextFieldPropertyEditorPresentation

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.