org.bonitasoft.studio.expression.editor.viewer.PatternExpressionViewer.java Source code

Java tutorial

Introduction

Here is the source code for org.bonitasoft.studio.expression.editor.viewer.PatternExpressionViewer.java

Source

/**
 * Copyright (C) 2012 BonitaSoft S.A.
 * BonitaSoft, 31 rue Gustave Eiffel - 38000 Grenoble
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2.0 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.bonitasoft.studio.expression.editor.viewer;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.bonitasoft.studio.common.ExpressionConstants;
import org.bonitasoft.studio.common.jface.databinding.validator.EmptyInputValidator;
import org.bonitasoft.studio.common.widgets.MagicComposite;
import org.bonitasoft.studio.expression.editor.i18n.Messages;
import org.bonitasoft.studio.expression.editor.provider.ExpressionContentProvider;
import org.bonitasoft.studio.expression.editor.provider.IExpressionNatureProvider;
import org.bonitasoft.studio.model.expression.Expression;
import org.bonitasoft.studio.model.expression.ExpressionPackage;
import org.bonitasoft.studio.pics.Pics;
import org.bonitasoft.studio.pics.PicsConstants;
import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.observable.value.IValueChangeListener;
import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.emf.databinding.EMFDataBindingContext;
import org.eclipse.emf.databinding.EMFObservables;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.databinding.swt.ISWTObservableValue;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextListener;
import org.eclipse.jface.text.TextEvent;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Link;

/**
 * @author Romain Bioteau
 *
 */
public class PatternExpressionViewer extends Composite {

    private TextViewer viewer;
    private ExpressionViewer expressionViewer;
    private final IExpressionNatureProvider expressionNatureProvider = new ExpressionContentProvider();
    private ExpressionContentAssistProcessor contentAssisProcessor;
    private final Set<ViewerFilter> filters = new HashSet<ViewerFilter>();
    protected Expression expression;
    private List<Expression> filteredExpressions;
    private PatternLineStyleListener patternLineStyle;
    private ControlDecoration hintDecoration;
    private ComputePatternDependenciesJob dependencyJob;
    private MagicComposite mc;
    private EMFDataBindingContext context;
    protected String mandatoryFieldLabel;
    private EObject contextInput;
    private Binding patternBinding;
    private ControlDecoration helpDecoration;

    public PatternExpressionViewer(Composite parent, int style) {
        super(parent, style);
        setLayout(GridLayoutFactory.fillDefaults().numColumns(1).margins(0, 0).create());
        mc = new MagicComposite(this, SWT.INHERIT_DEFAULT);
        mc.setLayout(GridLayoutFactory.fillDefaults().numColumns(1).margins(0, 0).extendedMargins(15, 25, 0, 0)
                .create());
        mc.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create());
        createTextViewer();
        createExpressionViewer();
        createEditorSwitch();
        mc.hide(getViewerControl());
        mc.show(expressionViewer.getControl());

    }

    private void createEditorSwitch() {
        final Link switchControl = new Link(mc, SWT.NONE);
        switchControl.setText(Messages.switchEditor);
        switchControl.setLayoutData(GridDataFactory.swtDefaults().align(SWT.END, SWT.CENTER).create());
        switchControl.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                switchEditorType();
            }
        });
    }

    protected void initializeEditorType() {
        if (ExpressionConstants.PATTERN_TYPE.equals(expression.getType())) {
            expression.setName("<pattern-expression>");
            mc.hide(expressionViewer.getControl());
            mc.show(getViewerControl());
            helpDecoration.show();
            mc.setLayout(GridLayoutFactory.fillDefaults().numColumns(1).margins(0, 0).extendedMargins(15, 25, 0, 0)
                    .create());
            bindPatternExpression();
        } else {
            mc.hide(getViewerControl());
            mc.show(expressionViewer.getControl());
            helpDecoration.hide();
            mc.setLayout(GridLayoutFactory.fillDefaults().numColumns(1).margins(0, 0).create());
            bindExpressionViewer();
        }
        mc.layout(true, true);
    }

    protected void switchEditorType() {
        if (MessageDialog.openQuestion(mc.getShell(), Messages.eraseExpressionTitle, Messages.eraseExpressionMsg)) {
            if (!expressionMode()) {
                showExpressionViewer();
                bindExpressionViewer();
                mc.layout(true, true);
            } else {
                showTextViewer();
                bindPatternExpression();
            }
        }
    }

    protected void showTextViewer() {
        mc.hide(expressionViewer.getControl());
        mc.show(getViewerControl());
        expression.setContent("");
        expression.setName("<pattern-expression>");
        expression.setInterpreter(null);
        expression.setType(ExpressionConstants.PATTERN_TYPE);
        bindPatternExpression();
        mc.setLayout(GridLayoutFactory.fillDefaults().numColumns(1).margins(0, 0).extendedMargins(15, 25, 0, 0)
                .create());
        mc.layout(true, true);
        helpDecoration.show();
        if (hintDecoration.getDescriptionText() != null) {
            hintDecoration.show();
        }
    }

    protected Control getViewerControl() {
        return viewer.getControl();
    }

    protected void showExpressionViewer() {
        helpDecoration.hide();
        hintDecoration.hide();
        mc.hide(getViewerControl());
        mc.show(expressionViewer.getControl());
        expression.setContent("");
        expression.setName("");
        expression.setInterpreter(null);
        expression.setType(ExpressionConstants.CONSTANT_TYPE);
        expression.getReferencedElements().clear();
        expressionViewer.setSelection(new StructuredSelection(expression));
        mc.setLayout(GridLayoutFactory.fillDefaults().numColumns(1).margins(0, 0).create());
    }

    protected boolean expressionMode() {
        return expressionViewer.getControl().isVisible();
    }

    private void bindExpressionViewer() {
        expressionViewer.setContext(contextInput);
        expressionViewer.setInput(contextInput);
        if (mandatoryFieldLabel != null) {
            expressionViewer.setMandatoryField(mandatoryFieldLabel, context);
        }
        expressionViewer.setExternalDataBindingContext(context);
        expressionViewer.setSelection(new StructuredSelection(expression));
    }

    protected void bindPatternExpression() {
        UpdateValueStrategy startegy = new UpdateValueStrategy();
        if (mandatoryFieldLabel != null) {
            startegy.setAfterConvertValidator(new EmptyInputValidator(mandatoryFieldLabel));
        }
        if (patternBinding != null) {
            patternBinding.dispose();
            patternBinding = null;
        }
        expression.getReferencedElements().clear();
        patternBinding = context.bindValue(SWTObservables.observeText(viewer.getTextWidget(), SWT.Modify),
                EMFObservables.observeValue(expression, ExpressionPackage.Literals.EXPRESSION__CONTENT), startegy,
                null);
    }

    protected void createExpressionViewer() {
        expressionViewer = new ExpressionViewer(mc, SWT.BORDER, null);
        expressionViewer.getControl().setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create());
    }

    protected void createTextViewer() {
        viewer = createViewer(mc);
        viewer.getControl().setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create());
        configureTextViewer();

        helpDecoration = new ControlDecoration(viewer.getControl(), SWT.TOP | SWT.RIGHT, this);
        helpDecoration.setImage(JFaceResources.getImage(Dialog.DLG_IMG_HELP));
        helpDecoration.setDescriptionText(Messages.patternViewerHelp);
        helpDecoration.setMarginWidth(2);
        helpDecoration.hide();

        hintDecoration = new ControlDecoration(viewer.getControl(), SWT.TOP | SWT.LEFT, this);
        hintDecoration.setImage(Pics.getImage(PicsConstants.hint));
        hintDecoration.setMarginWidth(2);
        hintDecoration.setShowHover(true);
        hintDecoration.setShowOnlyOnFocus(true);
        hintDecoration.hide();

        viewer.addTextListener(new ITextListener() {

            @Override
            public void textChanged(TextEvent event) {
                viewer.getTextWidget().notifyListeners(SWT.Modify, new Event());
            }
        });

        contentAssisProcessor = new ExpressionContentAssistProcessor(viewer.getDocument());
        final ContentAssistant assistant = new ContentAssistant();
        assistant.setContentAssistProcessor(contentAssisProcessor, IDocument.DEFAULT_CONTENT_TYPE);
        assistant.setShowEmptyList(true);
        assistant.enableAutoActivation(true);
        assistant.install(viewer);

        viewer.getTextWidget().addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {

                switch (e.keyCode) {
                case SWT.F1:
                    assistant.showPossibleCompletions();
                    break;
                default:
                    //ignore everything else
                }
            }

            @Override
            public void keyReleased(KeyEvent e) {
                if ((e.stateMask == SWT.CTRL || e.stateMask == SWT.COMMAND) && e.keyCode == SWT.SPACE) {
                    assistant.showPossibleCompletions();
                }
            }
        });

        ISWTObservableValue observable = SWTObservables.observeDelayedValue(400,
                SWTObservables.observeText(getTextControl(), SWT.Modify));
        observable.addValueChangeListener(new IValueChangeListener() {

            @Override
            public void handleValueChange(ValueChangeEvent event) {
                if (!expressionMode()) {
                    updateExpressionDependencies();
                }
            }
        });

        helpDecoration.show();
    }

    protected void configureTextViewer() {
        viewer.setDocument(new Document());
    }

    protected TextViewer createViewer(Composite parent) {
        return new TextViewer(parent, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);
    }

    private void updateExpressionDependencies() {
        dependencyJob.schedule();
    }

    @Override
    public void dispose() {
        super.dispose();
        if (dependencyJob != null) {
            dependencyJob.cancel();
        }
    }

    public void setContextInput(EObject input) {
        this.contextInput = input;
        manageNatureProviderAndAutocompletionProposal(input);
    }

    public void setExpression(final Expression expression) {
        this.expression = expression;
        initializeEditorType();
    }

    protected void manageNatureProviderAndAutocompletionProposal(Object input) {
        if (expressionNatureProvider != null) {
            expressionNatureProvider.setContext((EObject) input);
        }
        filteredExpressions = getFilteredExpressions();
        Set<Expression> expressionSet = new HashSet<Expression>(filteredExpressions);
        contentAssisProcessor.setExpressions(expressionSet);
        if (patternLineStyle != null) {
            patternLineStyle.setExpressions(expressionSet);
        }
        dependencyJob = new ComputePatternDependenciesJob(viewer.getDocument(), filteredExpressions);
        dependencyJob.addJobChangeListener(new IJobChangeListener() {

            @Override
            public void aboutToRun(IJobChangeEvent event) {
            }

            @Override
            public void awake(IJobChangeEvent event) {
            }

            @Override
            public void done(IJobChangeEvent event) {
                if (dependencyJob != null) {
                    List<EObject> deps = dependencyJob.getDependencies(viewer.getDocument().get());
                    expression.getReferencedElements().clear();
                    if (deps != null && !deps.isEmpty()) {
                        expression.getReferencedElements().addAll(deps);
                    }
                }
            }

            @Override
            public void running(IJobChangeEvent event) {
            }

            @Override
            public void scheduled(IJobChangeEvent event) {
            }

            @Override
            public void sleeping(IJobChangeEvent event) {
            }
        });
    }

    private List<Expression> getFilteredExpressions() {
        List<Expression> filteredExpressions = new ArrayList<Expression>();
        Expression[] expressions = expressionNatureProvider.getExpressions();
        EObject input = expressionNatureProvider.getContext();
        if (expressions != null) {
            filteredExpressions.addAll(Arrays.asList(expressions));
            if (input != null) {
                for (Expression exp : expressions) {
                    for (ViewerFilter filter : filters) {
                        if (filter != null && !filter.select(viewer, input, exp)) {
                            filteredExpressions.remove(exp);
                        }
                    }
                }
            }
        }
        return filteredExpressions;
    }

    public void addFilter(ViewerFilter viewerFilter) {
        filters.add(viewerFilter);
        expressionViewer.addFilter(viewerFilter);
    }

    public StyledText getTextControl() {
        return viewer.getTextWidget();
    }

    public void setHint(String hint) {
        hintDecoration.setDescriptionText(hint);
        hintDecoration.show();
        expressionViewer.setMessage(hint, IStatus.INFO);
    }

    public void setEMFBindingContext(EMFDataBindingContext context) {
        this.context = context;
    }

    public void setMandatoryField(String mandatoryFieldLabel) {
        this.mandatoryFieldLabel = mandatoryFieldLabel;
    }
}