com.github.jknack.antlr4ide.ui.railroad.actions.RailroadSelectionLinker.java Source code

Java tutorial

Introduction

Here is the source code for com.github.jknack.antlr4ide.ui.railroad.actions.RailroadSelectionLinker.java

Source

/*******************************************************************************
 * Copyright (c) 2010 itemis AG (http://www.itemis.eu)
 * 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:
 *   Jan Koehnlein - Initial API and implementation
 *******************************************************************************/
package com.github.jknack.antlr4ide.ui.railroad.actions;

import org.eclipse.draw2d.IFigure;
import org.eclipse.emf.common.util.URI;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.IPostSelectionProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.swt.widgets.Display;
import org.eclipse.xtext.Constants;
import org.eclipse.xtext.ui.editor.IURIEditorOpener;
import org.eclipse.xtext.ui.editor.XtextEditor;

import com.github.jknack.antlr4ide.ui.railroad.RailroadSelectionProvider;
import com.github.jknack.antlr4ide.ui.railroad.RailroadView;
import com.github.jknack.antlr4ide.ui.railroad.RailroadViewPreferences;
import com.github.jknack.antlr4ide.ui.railroad.figures.IEObjectReferer;
import com.github.jknack.antlr4ide.ui.railroad.figures.ISelectable;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.name.Named;

@Singleton
public class RailroadSelectionLinker implements IPropertyChangeListener {

    @Inject
    @Named(Constants.LANGUAGE_NAME)
    private String language;

    @Inject
    private IURIEditorOpener uriEditorOpener;

    @Inject
    private RailroadView view;

    private XtextEditor currentEditor;

    private ISelectable currentSelectedNode;

    @Inject
    private RailroadViewPreferences preferences;

    private ISelectionChangedListener diagramSelectionChangeListener = new ISelectionChangedListener() {
        @Override
        public void selectionChanged(final SelectionChangedEvent event) {
            if (view.getControl().isFocusControl()) {
                diagramSelectionChanged(event);
            }
        }
    };

    private ISelectionChangedListener textSelectionChangeListener = new ISelectionChangedListener() {
        @Override
        public void selectionChanged(final SelectionChangedEvent event) {
            if (preferences.isLinkWithEditor() && view.getSite().getPage().getActivePart() != view) {
                textSelectionChanged(event);
            }
        }
    };

    public void activate() {
        view.getSite().getSelectionProvider().addSelectionChangedListener(diagramSelectionChangeListener);
        preferences.getPreferenceStore().addPropertyChangeListener(this);
        if (preferences.isLinkWithEditor()) {
            selectGrammarText(currentSelectedNode, false);
        }
    }

    public void deactivate() {
        view.getSite().getSelectionProvider().removeSelectionChangedListener(diagramSelectionChangeListener);
        if (currentEditor != null) {
            removeTextSelectionListener(currentEditor);
        }
        preferences.getPreferenceStore().removePropertyChangeListener(this);
    }

    protected void selectFigure(IFigure selectedFigure) {
        while (selectedFigure != null && !(selectedFigure instanceof IEObjectReferer)) {
            selectedFigure = selectedFigure.getParent();
        }
        if (selectedFigure != null) {
            if (currentSelectedNode != null) {
                currentSelectedNode.setSelected(false);
            }
            if (selectedFigure instanceof ISelectable) {
                ((ISelectable) selectedFigure).setSelected(true);
                currentSelectedNode = (ISelectable) selectedFigure;
            } else {
                currentSelectedNode = null;
            }
        }
    }

    protected void selectGrammarText(final IFigure selectedFigure, final boolean isActivateEditor) {
        if (selectedFigure != null) {
            IEObjectReferer element = (IEObjectReferer) selectedFigure;
            final URI grammarElementURI = element.getEObjectURI();
            if (grammarElementURI != null) {
                final boolean isSelectElement = selectedFigure instanceof ISelectable;
                // enqueue to make sure the diagram is updated before
                if (isActivateEditor && isSelectElement) {
                    Display.getDefault().asyncExec(new Runnable() {
                        @Override
                        public void run() {
                            uriEditorOpener.open(grammarElementURI, isSelectElement);
                        }
                    });
                } else {
                    uriEditorOpener.open(grammarElementURI, isSelectElement);
                    view.getSite().getPage().activate(view);
                }
            }
        }
    }

    public void diagramSelectionChanged(final SelectionChangedEvent event) {
        ISelection selection = event.getSelection();
        if (selection instanceof IStructuredSelection) {
            IStructuredSelection structuredSelection = (IStructuredSelection) selection;
            if (structuredSelection.size() == 1) {
                Object selectedElement = structuredSelection.getFirstElement();
                if (selectedElement instanceof IFigure) {
                    IFigure selectedFigure = (IFigure) selectedElement;
                    selectFigure(selectedFigure);
                    boolean isDoubleClick = event instanceof RailroadSelectionProvider.DoubleClickEvent;
                    if ((currentEditor == null
                            || !currentEditor.getInternalSourceViewer().getTextWidget().isFocusControl())
                            && (isDoubleClick || preferences.isLinkWithEditor())) {
                        selectGrammarText(selectedFigure, isDoubleClick);
                    }
                }
            }
        }
    }

    public void textSelectionChanged(final SelectionChangedEvent event) {
        ISelection selection = event.getSelection();
        if (selection instanceof ITextSelection && !selection.isEmpty()) {
            ITextSelection textSelection = (ITextSelection) selection;
            int offset = textSelection.getOffset();
            IFigure figureToBeSelected = findFigureForTextOffset(view.getContents(), offset, null);
            if (figureToBeSelected != null) {
                selectFigure(figureToBeSelected);
                view.reveal(figureToBeSelected);
            }
        }
    }

    protected ISelectable findFigureForTextOffset(final IFigure figure, final int offset,
            ISelectable currentBestFigure) {
        if (figure == null) {
            return null;
        }
        if (figure instanceof ISelectable) {
            Region textRegion = ((ISelectable) figure).getTextRegion();
            if (textRegion != null && textRegion.getOffset() <= offset
                    && textRegion.getOffset() + textRegion.getLength() >= offset) {
                if (currentBestFigure == null
                        || currentBestFigure.getTextRegion().getLength() > textRegion.getLength()) {
                    currentBestFigure = (ISelectable) figure;
                }
            }
        }
        for (Object child : figure.getChildren()) {
            if (child instanceof IFigure) {
                currentBestFigure = findFigureForTextOffset((IFigure) child, offset, currentBestFigure);
            }
        }
        return currentBestFigure;
    }

    @Override
    public void propertyChange(final PropertyChangeEvent event) {
        if (event.getProperty().equals(RailroadViewPreferences.LINK_WITH_EDITOR_KEY)
                && event.getNewValue() == Boolean.TRUE) {
            if (currentSelectedNode != null) {
                selectGrammarText(currentSelectedNode, true);
            }
        }
    }

    public void setXtextEditor(final XtextEditor xtextEditor) {
        if (currentEditor != null) {
            removeTextSelectionListener(currentEditor);
        }
        if (language.equals(xtextEditor.getLanguageName())) {
            currentEditor = xtextEditor;
            ISelectionProvider selectionProvider = xtextEditor.getSelectionProvider();
            if (selectionProvider instanceof IPostSelectionProvider) {
                ((IPostSelectionProvider) selectionProvider)
                        .addPostSelectionChangedListener(textSelectionChangeListener);
            } else {
                selectionProvider.addSelectionChangedListener(textSelectionChangeListener);
            }
        }
    }

    protected void removeTextSelectionListener(final XtextEditor editor) {
        ISelectionProvider selectionProvider = editor.getSelectionProvider();
        if (selectionProvider != null) {
            if (selectionProvider instanceof IPostSelectionProvider) {
                ((IPostSelectionProvider) selectionProvider)
                        .removePostSelectionChangedListener(textSelectionChangeListener);
            } else {
                selectionProvider.removeSelectionChangedListener(textSelectionChangeListener);
            }
        }
    }
}