Package org.eclipse.wst.sse.ui.internal.style

Source Code of org.eclipse.wst.sse.ui.internal.style.SemanticHighlightingReconciler

/*******************************************************************************
* Copyright (c) 2009, 2011 IBM Corporation and others.
* 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:
*     IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.sse.ui.internal.style;

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

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextPresentation;
import org.eclipse.jface.text.reconciler.DirtyRegion;
import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.wst.sse.core.internal.model.ModelManagerImpl;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.ui.ISemanticHighlighting;
import org.eclipse.wst.sse.ui.ISemanticHighlightingExtension;
import org.eclipse.wst.sse.ui.internal.Logger;
import org.eclipse.wst.sse.ui.internal.style.SemanticHighlightingManager.HighlightedPosition;
import org.eclipse.wst.sse.ui.internal.style.SemanticHighlightingManager.HighlightingStyle;

/**
* Semantic highlighting reconciler for Structured Source Editors. Based on
* org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightingReconciler
*
* @since 3.1
*/
public class SemanticHighlightingReconciler implements IReconcilingStrategy, IReconcilingStrategyExtension {

  private IDocument fDocument;

  private ITextViewer fViewer;
  private SemanticHighlightingPresenter fPresenter;
  private ISemanticHighlighting[] fSemanticHighlightings;
  private HighlightingStyle[] fHighlightings;

  private List fAddedPositions = new ArrayList();
  private List fRemovedPositions = new ArrayList();
  /** Number of removed positions */
  private int fNOfRemovedPositions;
 
  /** Background job */
  private Job fJob;
  /** Background job lock */
  private final Object fJobLock = new Object();
 
  /** Reconcile operation lock. */
  private final Object fReconcileLock = new Object();
  private boolean fIsReconciling = false;
  /** The semantic highlighting presenter - cache for background thread, only valid during {@link #reconcile(IRegion)} */
  private SemanticHighlightingPresenter fJobPresenter;
  /** Semantic highlightings - cache for background thread, only valid during {@link #reconcile(IRegion)} */
  private ISemanticHighlighting[] fJobSemanticHighlightings;
  /** HighlightingStyle - cache for background thread, only valid during {@link #reconcile(IRegion)} */
  private HighlightingStyle[] fJobHighlightings;

  private boolean fIsInstalled;

  public void install(ITextViewer sourceViewer, SemanticHighlightingPresenter presenter, ISemanticHighlighting[] semanticHighlightings, HighlightingStyle[] highlightings) {
    fViewer = sourceViewer;
    fPresenter = presenter;
    fSemanticHighlightings = semanticHighlightings;
    fHighlightings = highlightings;
    fIsInstalled = true;
  }

  public void uninstall() {
    fIsInstalled = false;
    fViewer = null;
    fPresenter = null;
    fSemanticHighlightings = null;
    fHighlightings = null;
  }

  public void reconcile(IRegion partition) {
    // ensure at most one thread can be reconciling at any time
    synchronized (fReconcileLock) {
      if (fIsReconciling)
        return;
      else
        fIsReconciling= true;
    }
    fJobPresenter = fPresenter;
    fJobSemanticHighlightings = fSemanticHighlightings;
    fJobHighlightings = fHighlightings;
    IStructuredModel model = null;
    try {
      if (fJobPresenter == null || fJobSemanticHighlightings == null || fJobHighlightings == null || fDocument == null)
        return;

      fJobPresenter.setCanceled(false);
   
      startReconcilingPositions();
      IStructuredDocument document = (IStructuredDocument) fDocument;
      model = ModelManagerImpl.getInstance().getModelForRead(document);
      IStructuredDocumentRegion[] regions = document.getStructuredDocumentRegions(partition.getOffset(), partition.getLength());
      for (int i = 0; i < regions.length && fIsInstalled; i++) {
        if (document.containsReadOnly(regions[i].getStartOffset(), regions[i].getLength()))
          addPosition(new Position(regions[i].getStartOffset(), regions[i].getLength()), null, true);
        else {
          for (int j = 0; j < fJobSemanticHighlightings.length && fIsInstalled; j++) {
            if (fJobHighlightings[j].isEnabled()) {
              Position[] consumes = null;
              if (fJobSemanticHighlightings[j] instanceof ISemanticHighlightingExtension && model != null) {
                consumes = ((ISemanticHighlightingExtension) fJobSemanticHighlightings[j]).consumes(regions[i], model.getIndexedRegion(regions[i].getStartOffset()));
              }
              else {
                consumes = fJobSemanticHighlightings[j].consumes(regions[i]);
              }
              if (consumes != null) {
                for (int k = 0; k < consumes.length; k++)
                  addPosition(consumes[k], fJobHighlightings[j]);
              }
            }
          }
        }
      }

      if (fIsInstalled) {
        List oldPositions = fRemovedPositions;
        List newPositions = new ArrayList(fNOfRemovedPositions);
        for (int i = 0, n = oldPositions.size(); i < n && fIsInstalled; i++) {
          Object current = oldPositions.get(i);
          if (current != null)
            newPositions.add(current);
        }
        fRemovedPositions = newPositions;
       
        TextPresentation presentation = null;
        if (!fJobPresenter.isCanceled())
          presentation = fJobPresenter.createPresentation(fAddedPositions, fRemovedPositions);
        if (!fJobPresenter.isCanceled())
          updatePresentation(presentation, fAddedPositions, fRemovedPositions);
      }
      stopReconcilingPositions();
    }
    finally {
      fJobPresenter= null;
      fJobSemanticHighlightings= null;
      fJobHighlightings= null;
      if (model != null)
        model.releaseFromRead();
      synchronized (fReconcileLock) {
        fIsReconciling= false;
      }
    }
  }

  private void addPosition(Position position, HighlightingStyle highlighting) {
    addPosition(position, highlighting, false);
  }

  private void addPosition(Position position, HighlightingStyle highlighting, boolean isReadOnly) {
    boolean isExisting = false;
    // TODO: use binary search
    for (int i = 0, n = fRemovedPositions.size(); i < n; i++) {
      HighlightedPosition highlightedPosition = (HighlightedPosition) fRemovedPositions.get(i);
      if (highlightedPosition == null)
        continue;
      if (highlightedPosition.isEqual(position, highlighting)) {
        isExisting = true;
        fRemovedPositions.set(i, null);
        fNOfRemovedPositions--;
        break;
      }
    }
    if (!isExisting) {
      fAddedPositions.add(fJobPresenter.createHighlightedPosition(position, highlighting, isReadOnly));
    }
  }

  /**
   * Update the presentation.
   *
   * @param textPresentation
   *            the text presentation
   * @param addedPositions
   *            the added positions
   * @param removedPositions
   *            the removed positions
   */
  private void updatePresentation(TextPresentation textPresentation, List addedPositions, List removedPositions) {
    Runnable runnable = fJobPresenter.createUpdateRunnable(textPresentation, addedPositions, removedPositions);
    if (runnable == null)
      return;

    if (fViewer == null)
      return;

    Control viewerControl = fViewer.getTextWidget();
    if (viewerControl == null)
      return;

    Display display = viewerControl.getDisplay();
    if (display == null || display.isDisposed())
      return;

    display.asyncExec(runnable);
  }

  /**
   * Start reconciling positions.
   */
  private void startReconcilingPositions() {
    fJobPresenter.addAllPositions(fRemovedPositions);
    fNOfRemovedPositions = fRemovedPositions.size();
  }

  /**
   * Stop reconciling positions.
   */
  private void stopReconcilingPositions() {
    fRemovedPositions.clear();
    fNOfRemovedPositions = 0;
    fAddedPositions.clear();
  }

  public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
    reconcile(dirtyRegion);
  }

  public void setDocument(IDocument document) {
    fDocument = document;
//    refresh();
  }

  public void initialReconcile() {
    // Do nothing
  }

  public void setProgressMonitor(IProgressMonitor monitor) {
  }
 
  /**
   * Schedule a background job for reconciling the Semantic Highlighting model.
   */
  private void scheduleJob() {
    synchronized (fJobLock) {
      final Job oldJob= fJob;
      if (fJob != null) {
        fJob.cancel();
        fJob= null;
      }

      fJob= new Job("Semantic Highlighting Job") {
        protected IStatus run(IProgressMonitor monitor) {
          if (oldJob != null) {
            try {
              oldJob.join();
            } catch (InterruptedException e) {
              Logger.logException(e);
              return Status.CANCEL_STATUS;
            }
          }
          if (monitor.isCanceled())
            return Status.CANCEL_STATUS;

          reconcile(new Region(0, fDocument.getLength()));
          synchronized (fJobLock) {
            // allow the job to be gc'ed
            if (fJob == this)
              fJob= null;
          }
          return Status.OK_STATUS;
        }
      };
      fJob.setSystem(true);
      fJob.setPriority(Job.DECORATE);
      fJob.schedule();
    }
  }

  public void refresh() {
    if (fDocument != null)
      scheduleJob();
  }
}
TOP

Related Classes of org.eclipse.wst.sse.ui.internal.style.SemanticHighlightingReconciler

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.