Package it.tref.eclipse.wicket.plugin.editors

Source Code of it.tref.eclipse.wicket.plugin.editors.SelectionListenerWithASTManager

package it.tref.eclipse.wicket.plugin.editors;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.internal.ui.JavaUIMessages;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.jdt.internal.ui.viewsupport.ISelectionListenerWithAST;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.texteditor.ITextEditor;

/**
* Selection listener that can manage AST from MultiPage editor
* This class is a bug fix of the original one in the Eclipse source
*
* @author Andrea Fantappi�
*/
@SuppressWarnings("restriction")
public class SelectionListenerWithASTManager
{
  private static SelectionListenerWithASTManager fgDefault;
 
  /**
   * @return Returns the default manager instance.
   */
  public static SelectionListenerWithASTManager getDefault() {
    if (fgDefault == null) {
      fgDefault= new SelectionListenerWithASTManager();
    }
    return fgDefault;
  }
 
  private final static class PartListenerGroup
  {
    private ITextEditor fPart;
    private ISelectionListener fPostSelectionListener;
    private ISelectionChangedListener fSelectionListener;
    private Job fCurrentJob;
    private ListenerList fAstListeners;
    /**
     * Lock to avoid having more than one calculateAndInform job in parallel.
     * Only jobs may synchronize on this as otherwise deadlocks are possible.
     */
    private final Object fJobLock = new Object();
   
    public PartListenerGroup(ITextEditor editorPart)
    {
      fPart= editorPart;
      fCurrentJob= null;
      fAstListeners= new ListenerList(ListenerList.IDENTITY);
     
      fSelectionListener= new ISelectionChangedListener()
      {
        public void selectionChanged(SelectionChangedEvent event) {
          ISelection selection= event.getSelection();
          if (selection instanceof ITextSelection) {
            fireSelectionChanged((ITextSelection) selection);
          }
        }
      };
     
      fPostSelectionListener= new ISelectionListener()
      {
        public void selectionChanged(IWorkbenchPart part, ISelection selection) {
          if (part instanceof WicketFunEditor && selection instanceof ITextSelection)
            firePostSelectionChanged((ITextSelection) selection);
        }
      };
    }

    public boolean isEmpty() {
      return fAstListeners.isEmpty();
    }

    public void install(ISelectionListenerWithAST listener)
    {
      if (isEmpty()) {
        fPart.getEditorSite().getPage().addPostSelectionListener(fPostSelectionListener);
        ISelectionProvider selectionProvider= fPart.getSelectionProvider();
        if (selectionProvider != null)
            selectionProvider.addSelectionChangedListener(fSelectionListener);
      }
      fAstListeners.add(listener);
    }
   
    public void uninstall(ISelectionListenerWithAST listener)
    {
      fAstListeners.remove(listener);
      if (isEmpty()) {
        fPart.getEditorSite().getPage().removePostSelectionListener(fPostSelectionListener);
        ISelectionProvider selectionProvider= fPart.getSelectionProvider();
        if (selectionProvider != null)
          selectionProvider.removeSelectionChangedListener(fSelectionListener);
      }
    }
   
    /**
     * A selection event has occurred.
     *
     * @param selection the selection
     */
    public void fireSelectionChanged(final ITextSelection selection)
    {
      if (fCurrentJob != null) {
        fCurrentJob.cancel();
      }
    }
   
    /**
     * A post selection event has occurred.
     *
     * @param selection the selection
     */
    public void firePostSelectionChanged(final ITextSelection selection)
    {
      if (fCurrentJob != null) {
        fCurrentJob.cancel();
      }
      IJavaElement input= EditorUtility.getEditorInputJavaElement(fPart, false);
      if (!(input instanceof ITypeRoot)) {
        return;
      }
      final ITypeRoot typeRoot= (ITypeRoot) input;
     
     
      fCurrentJob= new Job(JavaUIMessages.SelectionListenerWithASTManager_job_title)
      {
        public IStatus run(IProgressMonitor monitor)
        {
          if (monitor == null) {
            monitor= new NullProgressMonitor();
          }
          synchronized (fJobLock) {
            return calculateASTandInform(typeRoot, selection, monitor);
          }
        }
      };
      fCurrentJob.setPriority(Job.DECORATE);
      fCurrentJob.setSystem(true);
      fCurrentJob.schedule();
    }
   
    protected final IStatus calculateASTandInform(ITypeRoot input, ITextSelection selection, IProgressMonitor monitor)
    {
      if (monitor.isCanceled()) {
        return Status.CANCEL_STATUS;
      }
     
      // create AST
      try
      {
        // use the parser directly, the use of static shared classes don't work with multipage editor
        ASTParser parser = ASTParser.newParser(AST.JLS3);
        parser.setResolveBindings(true);
        parser.setStatementsRecovery(true);
        parser.setBindingsRecovery(true);
        parser.setSource(input);
       
        CompilationUnit astRoot = (CompilationUnit)parser.createAST(monitor);
       
        if (astRoot != null && !monitor.isCanceled()) {
          Object[] listeners;
          synchronized (PartListenerGroup.this) {
            listeners= fAstListeners.getListeners();
          }
          for (int i= 0; i < listeners.length; i++)
          {
            ((ISelectionListenerWithAST) listeners[i]).selectionChanged(fPart, selection, astRoot);
            if (monitor.isCanceled()) {
              return Status.CANCEL_STATUS;
            }
          }
          return Status.OK_STATUS;
        }
      } catch (OperationCanceledException e) {
        // thrown when canceling the AST creation
      }
      return Status.CANCEL_STATUS;
    }
  }
 
  @SuppressWarnings("rawtypes")
  private Map fListenerGroups;
 
  @SuppressWarnings("rawtypes")
  private SelectionListenerWithASTManager() {
    fListenerGroups = new HashMap();
  }
 
  /**
   * Registers a selection listener for the given editor part.
   * @param part The editor part to listen to.
   * @param listener The listener to register.
   */
  @SuppressWarnings({ "unchecked" })
  public void addListener(ITextEditor part, ISelectionListenerWithAST listener)
  {
    synchronized (this)
    {
      PartListenerGroup partListener= (PartListenerGroup) fListenerGroups.get(part);
      if (partListener == null) {
        partListener= new PartListenerGroup(part);
        fListenerGroups.put(part, partListener);
      }
      partListener.install(listener);
    }
  }

  /**
   * Unregisters a selection listener.
   * @param part The editor part the listener was registered.
   * @param listener The listener to unregister.
   */
  public void removeListener(ITextEditor part, ISelectionListenerWithAST listener)
  {
    synchronized (this)
    {
      PartListenerGroup partListener= (PartListenerGroup) fListenerGroups.get(part);
      if (partListener != null) {
        partListener.uninstall(listener);
        if (partListener.isEmpty()) {
          fListenerGroups.remove(part);
        }
      }
    }
  }
}
TOP

Related Classes of it.tref.eclipse.wicket.plugin.editors.SelectionListenerWithASTManager

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.