intial source from ttp://www.sf.net/projects/wdte
[phpeclipse.git] / archive / net.sourceforge.phpeclipse.css.ui / src / net / sourceforge / phpeclipse / css / ui / internal / text / CssReconcileStep.java
diff --git a/archive/net.sourceforge.phpeclipse.css.ui/src/net/sourceforge/phpeclipse/css/ui/internal/text/CssReconcileStep.java b/archive/net.sourceforge.phpeclipse.css.ui/src/net/sourceforge/phpeclipse/css/ui/internal/text/CssReconcileStep.java
new file mode 100644 (file)
index 0000000..d5cbc26
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * 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: CssReconcileStep.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.text;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import net.sourceforge.phpeclipse.css.core.model.IStyleSheet;
+import net.sourceforge.phpeclipse.css.core.parser.IProblem;
+import net.sourceforge.phpeclipse.css.core.parser.IProblemCollector;
+import net.sourceforge.phpeclipse.css.core.parser.LexicalErrorException;
+import net.sourceforge.phpeclipse.css.core.parser.SyntaxErrorException;
+import net.sourceforge.phpeclipse.css.ui.internal.CssDocumentProvider;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.reconciler.AbstractReconcileStep;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconcilableModel;
+import org.eclipse.jface.text.reconciler.IReconcileResult;
+import org.eclipse.jface.text.reconciler.IReconcileStep;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Implementation of a reconcile step for building the CSS parse tree on changes
+ * to the editor content.
+ */
+public class CssReconcileStep extends AbstractReconcileStep {
+
+       // Inner Classes -----------------------------------------------------------
+
+       /**
+        * Adapts an <code>IStyleSheet</code> to the <code>IReconcilableModel</code>
+        * interface.
+        */
+       private class StyleSheetAdapter implements IReconcilableModel {
+
+               private IStyleSheet styleSheet;
+
+               public StyleSheetAdapter(IStyleSheet styleSheet) {
+                       this.styleSheet = styleSheet;
+               }
+
+               public IStyleSheet getStyleSheet() {
+                       return styleSheet;
+               }
+
+       }
+
+       /**
+        * Implementation of the problem collector interface for creating problem
+        * annotations when there are problems parsing the style sheet.
+        */
+       private class ProblemCollector implements IProblemCollector {
+
+               /**
+                * The list of problems added to this collector.
+                */
+               private List collectedProblems = new ArrayList();
+
+               /**
+                * @see IProblemCollector#addProblem(IProblem)
+                */
+               public void addProblem(IProblem problem) {
+                       collectedProblems.add(problem);
+               }
+
+               /**
+                * Returns the list of problems collected while the CSS source has been
+                * parsed, in the order they were reported. The list returned is
+                * immutable.
+                * 
+                * @return the list of collected problems (of type {@link IProblem})
+                */
+               public List getProblems() {
+                       return Collections.unmodifiableList(collectedProblems);
+               }
+
+       }
+
+       /**
+        * Adapter that adapts an {@link IProblem} to an {@link Annotation}.
+        */
+       private class ProblemAdapter extends AnnotationAdapter {
+
+               private IProblem problem;
+               private Position position;
+
+               ProblemAdapter(IProblem problem)  {
+                       this.problem = problem;
+               }
+
+               public Position getPosition()  {
+                       if (position == null) {
+                               position = createPositionFromProblem();
+                       }
+                       return position;
+               }
+
+               public Annotation createAnnotation() {
+                       int start = problem.getSourceStart();
+                       if (start < 0) {
+                               return null;
+                       }
+                       int length = problem.getSourceEnd() - problem.getSourceStart() + 1;
+                       if (length < 0) {
+                               return null;
+                       }
+                       String type = null;
+                       if (problem.isWarning()) {
+                               type = "org.eclipse.ui.workbench.texteditor.warning"; //$NON-NLS-1$
+                       } else if (problem.isError()) {
+                               type = "org.eclipse.ui.workbench.texteditor.error"; //$NON-NLS-1$
+                       }
+                       return new Annotation(type, false, problem.getMessage());
+               }
+
+               private Position createPositionFromProblem() {
+                       int start = problem.getSourceStart();
+                       if (start < 0) {
+                               return null;
+                       }
+                       int length = problem.getSourceEnd() - problem.getSourceStart() + 1;
+                       if (length < 0) {
+                               return null;
+                       }
+                       return new Position(start, length);
+               }
+
+       }
+
+       // Instance Variables ------------------------------------------------------
+
+       private ITextEditor editor;
+
+       private StyleSheetAdapter styleSheetAdapter;
+
+       // Constructors ------------------------------------------------------------
+
+       /**
+        * Default constructor.
+        */
+       public CssReconcileStep(ITextEditor editor) {
+               this.editor = editor;
+               styleSheetAdapter = new StyleSheetAdapter(getStyleSheet());
+       }
+
+       /**
+        * Constructor.
+        * 
+        * @param step the step to add to the pipe
+        * @param editor the associated text editor
+        */
+       public CssReconcileStep(IReconcileStep step, ITextEditor editor) {
+               super(step);
+               this.editor = editor;
+               styleSheetAdapter = new StyleSheetAdapter(getStyleSheet());
+       }
+
+       // AbstractReconcileStep Implementation ------------------------------------
+
+       /*
+        * @see AbstractReconcileStep#reconcileModel(DirtyRegion, IRegion)
+        */
+       protected IReconcileResult[] reconcileModel(DirtyRegion dirtyRegion,
+               IRegion subRegion) {
+               IStyleSheet styleSheet = styleSheetAdapter.getStyleSheet();
+               ProblemCollector problemCollector = new ProblemCollector();
+               try {
+                       styleSheet.reconcile(problemCollector);
+               } catch (LexicalErrorException e) {
+                       // Already reported to the problem collector  
+               } catch (SyntaxErrorException e) {
+                       // Already reported to the problem collector  
+               }
+               List problems = problemCollector.getProblems();
+               IReconcileResult[] retVal = new IReconcileResult[problems.size()];
+               for (int i = 0; i < problems.size(); i++) {
+                       IProblem problem = (IProblem) problems.get(i);
+                       retVal[i] = new ProblemAdapter(problem);
+               }
+               return retVal;
+       }
+
+       /*
+        * @see AbstractReconcileStep#getModel()
+        */
+       public IReconcilableModel getModel() {
+               return styleSheetAdapter;
+       }
+
+       // Private Methods Implementation ------------------------------------------
+
+       /**
+        * Retrieve the style sheet associated with the editor input.
+        */
+       private IStyleSheet getStyleSheet() {
+               IDocumentProvider documentProvider = editor.getDocumentProvider();
+               if (documentProvider instanceof CssDocumentProvider) {
+                       CssDocumentProvider cssDocumentProvider = (CssDocumentProvider)
+                               documentProvider;
+                       return cssDocumentProvider.getStyleSheet(editor.getEditorInput());
+               }
+               return null;
+       }
+
+}