X-Git-Url: http://git.phpeclipse.com diff --git a/archive/net.sourceforge.phpeclipse.css.ui/src/net/sourceforge/phpeclipse/css/ui/internal/text/CssReconcilingStrategy.java b/archive/net.sourceforge.phpeclipse.css.ui/src/net/sourceforge/phpeclipse/css/ui/internal/text/CssReconcilingStrategy.java new file mode 100644 index 0000000..c1ab039 --- /dev/null +++ b/archive/net.sourceforge.phpeclipse.css.ui/src/net/sourceforge/phpeclipse/css/ui/internal/text/CssReconcilingStrategy.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2003-2004 Christopher Lenz and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Christopher Lenz - initial API and implementation + * + * $Id: CssReconcilingStrategy.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $ + */ + +package net.sourceforge.phpeclipse.css.ui.internal.text; + +import java.lang.reflect.InvocationTargetException; +import java.util.Iterator; + +import net.sourceforge.phpeclipse.css.ui.CssUI; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.reconciler.DirtyRegion; +import org.eclipse.jface.text.reconciler.IReconcileResult; +import org.eclipse.jface.text.reconciler.IReconcileStep; +import org.eclipse.jface.text.reconciler.IReconcilingStrategy; +import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.actions.WorkspaceModifyOperation; +import org.eclipse.ui.texteditor.ITextEditor; + + +/** + * Reconciling strategy for CSS style sheets. This class is responsible for + * keeping the parsed model in sync with the text. + */ +public class CssReconcilingStrategy + implements IReconcilingStrategy, IReconcilingStrategyExtension { + + // Instance Variables ------------------------------------------------------ + + /** + * The associated text editor. + */ + private ITextEditor editor; + + /** + * A progress monitor that should be used for long-running operations. + */ + IProgressMonitor progressMonitor; + + /** + * The first (and only) reconcile step is the parsing of the style sheet. + */ + private IReconcileStep firstStep; + + // Constructors ------------------------------------------------------------ + + public CssReconcilingStrategy(ITextEditor editor) { + this.editor = editor; + firstStep = new CssReconcileStep(editor); + } + + // IReconcilingStrategy Implementation ------------------------------------- + + /** + * @see IReconcilingStrategy#reconcile(DirtyRegion, IRegion) + */ + public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) { + removeTemporaryAnnotations(); + process(firstStep.reconcile(dirtyRegion, subRegion)); + } + + /** + * @see IReconcilingStrategy#reconcile(IRegion) + */ + public void reconcile(IRegion partition) { + removeTemporaryAnnotations(); + process(firstStep.reconcile(partition)); + } + + /** + * @see IReconcilingStrategy#setDocument(IDocument) + */ + public void setDocument(IDocument document) { + // FIXME + firstStep.setInputModel(null); //new DocumentAdapter(document); + } + + // IReconcilingStrategyExtension Implementation ---------------------------- + + /** + * @see IReconcilingStrategyExtension#initialReconcile() + */ + public void initialReconcile() { + process(firstStep.reconcile(null)); + } + + /** + * @see IReconcilingStrategyExtension#setProgressMonitor(IProgressMonitor) + */ + public void setProgressMonitor(IProgressMonitor monitor) { + firstStep.setProgressMonitor(monitor); + progressMonitor = monitor; + } + + // Private Methods --------------------------------------------------------- + + /** + * Returns the annotation model for the editor input. + * + * @return the annotation model + */ + IAnnotationModel getAnnotationModel() { + IEditorInput input = editor.getEditorInput(); + return editor.getDocumentProvider().getAnnotationModel(input); + } + + /** + * Adds results of the reconcilation to the annotation model. + */ + private void process(final IReconcileResult[] results) { + if (results == null) { + return; + } + + IRunnableWithProgress runnable = new WorkspaceModifyOperation() { + protected void execute(IProgressMonitor monitor) { + for (int i = 0; i < results.length; i++) { + if ((progressMonitor != null) + && (progressMonitor.isCanceled())) { + return; + } + + if (!(results[i] instanceof AnnotationAdapter)) { + continue; + } + + AnnotationAdapter result = (AnnotationAdapter) results[i]; + Position pos = result.getPosition(); + Annotation annotation = result.createAnnotation(); + getAnnotationModel().addAnnotation(annotation, pos); + } + } + }; + + try { + runnable.run(null); + } catch (InvocationTargetException e) { + CssUI.log(e); + } catch (InterruptedException e) { + CssUI.log(e); + } + + if (editor instanceof IReconcilingParticipant) { + ((IReconcilingParticipant) editor).reconciled(); + } + } + + /* + * TODO A "real" implementation must be smarter, i.e. don't remove and add + * the annotations which are the same. + */ + private void removeTemporaryAnnotations() { + Iterator i = getAnnotationModel().getAnnotationIterator(); + while (i.hasNext()) { + Annotation annotation = (Annotation) i.next(); + if (!annotation.isPersistent()) { + getAnnotationModel().removeAnnotation(annotation); + } + } + } +}