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
1 /*
2  * Copyright (c) 2003-2004 Christopher Lenz and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     Christopher Lenz - initial API and implementation
10  * 
11  * $Id: CssReconcileStep.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
12  */
13
14 package net.sourceforge.phpeclipse.css.ui.internal.text;
15
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.List;
19
20 import net.sourceforge.phpeclipse.css.core.model.IStyleSheet;
21 import net.sourceforge.phpeclipse.css.core.parser.IProblem;
22 import net.sourceforge.phpeclipse.css.core.parser.IProblemCollector;
23 import net.sourceforge.phpeclipse.css.core.parser.LexicalErrorException;
24 import net.sourceforge.phpeclipse.css.core.parser.SyntaxErrorException;
25 import net.sourceforge.phpeclipse.css.ui.internal.CssDocumentProvider;
26
27 import org.eclipse.jface.text.IRegion;
28 import org.eclipse.jface.text.Position;
29 import org.eclipse.jface.text.reconciler.AbstractReconcileStep;
30 import org.eclipse.jface.text.reconciler.DirtyRegion;
31 import org.eclipse.jface.text.reconciler.IReconcilableModel;
32 import org.eclipse.jface.text.reconciler.IReconcileResult;
33 import org.eclipse.jface.text.reconciler.IReconcileStep;
34 import org.eclipse.jface.text.source.Annotation;
35 import org.eclipse.ui.texteditor.IDocumentProvider;
36 import org.eclipse.ui.texteditor.ITextEditor;
37
38 /**
39  * Implementation of a reconcile step for building the CSS parse tree on changes
40  * to the editor content.
41  */
42 public class CssReconcileStep extends AbstractReconcileStep {
43
44         // Inner Classes -----------------------------------------------------------
45
46         /**
47          * Adapts an <code>IStyleSheet</code> to the <code>IReconcilableModel</code>
48          * interface.
49          */
50         private class StyleSheetAdapter implements IReconcilableModel {
51
52                 private IStyleSheet styleSheet;
53
54                 public StyleSheetAdapter(IStyleSheet styleSheet) {
55                         this.styleSheet = styleSheet;
56                 }
57
58                 public IStyleSheet getStyleSheet() {
59                         return styleSheet;
60                 }
61
62         }
63
64         /**
65          * Implementation of the problem collector interface for creating problem
66          * annotations when there are problems parsing the style sheet.
67          */
68         private class ProblemCollector implements IProblemCollector {
69
70                 /**
71                  * The list of problems added to this collector.
72                  */
73                 private List collectedProblems = new ArrayList();
74
75                 /**
76                  * @see IProblemCollector#addProblem(IProblem)
77                  */
78                 public void addProblem(IProblem problem) {
79                         collectedProblems.add(problem);
80                 }
81
82                 /**
83                  * Returns the list of problems collected while the CSS source has been
84                  * parsed, in the order they were reported. The list returned is
85                  * immutable.
86                  * 
87                  * @return the list of collected problems (of type {@link IProblem})
88                  */
89                 public List getProblems() {
90                         return Collections.unmodifiableList(collectedProblems);
91                 }
92
93         }
94
95         /**
96          * Adapter that adapts an {@link IProblem} to an {@link Annotation}.
97          */
98         private class ProblemAdapter extends AnnotationAdapter {
99
100                 private IProblem problem;
101                 private Position position;
102
103                 ProblemAdapter(IProblem problem)  {
104                         this.problem = problem;
105                 }
106
107                 public Position getPosition()  {
108                         if (position == null) {
109                                 position = createPositionFromProblem();
110                         }
111                         return position;
112                 }
113
114                 public Annotation createAnnotation() {
115                         int start = problem.getSourceStart();
116                         if (start < 0) {
117                                 return null;
118                         }
119                         int length = problem.getSourceEnd() - problem.getSourceStart() + 1;
120                         if (length < 0) {
121                                 return null;
122                         }
123                         String type = null;
124                         if (problem.isWarning()) {
125                                 type = "org.eclipse.ui.workbench.texteditor.warning"; //$NON-NLS-1$
126                         } else if (problem.isError()) {
127                                 type = "org.eclipse.ui.workbench.texteditor.error"; //$NON-NLS-1$
128                         }
129                         return new Annotation(type, false, problem.getMessage());
130                 }
131
132                 private Position createPositionFromProblem() {
133                         int start = problem.getSourceStart();
134                         if (start < 0) {
135                                 return null;
136                         }
137                         int length = problem.getSourceEnd() - problem.getSourceStart() + 1;
138                         if (length < 0) {
139                                 return null;
140                         }
141                         return new Position(start, length);
142                 }
143
144         }
145
146         // Instance Variables ------------------------------------------------------
147
148         private ITextEditor editor;
149
150         private StyleSheetAdapter styleSheetAdapter;
151
152         // Constructors ------------------------------------------------------------
153
154         /**
155          * Default constructor.
156          */
157         public CssReconcileStep(ITextEditor editor) {
158                 this.editor = editor;
159                 styleSheetAdapter = new StyleSheetAdapter(getStyleSheet());
160         }
161
162         /**
163          * Constructor.
164          * 
165          * @param step the step to add to the pipe
166          * @param editor the associated text editor
167          */
168         public CssReconcileStep(IReconcileStep step, ITextEditor editor) {
169                 super(step);
170                 this.editor = editor;
171                 styleSheetAdapter = new StyleSheetAdapter(getStyleSheet());
172         }
173
174         // AbstractReconcileStep Implementation ------------------------------------
175
176         /*
177          * @see AbstractReconcileStep#reconcileModel(DirtyRegion, IRegion)
178          */
179         protected IReconcileResult[] reconcileModel(DirtyRegion dirtyRegion,
180                 IRegion subRegion) {
181                 IStyleSheet styleSheet = styleSheetAdapter.getStyleSheet();
182                 ProblemCollector problemCollector = new ProblemCollector();
183                 try {
184                         styleSheet.reconcile(problemCollector);
185                 } catch (LexicalErrorException e) {
186                         // Already reported to the problem collector  
187                 } catch (SyntaxErrorException e) {
188                         // Already reported to the problem collector  
189                 }
190                 List problems = problemCollector.getProblems();
191                 IReconcileResult[] retVal = new IReconcileResult[problems.size()];
192                 for (int i = 0; i < problems.size(); i++) {
193                         IProblem problem = (IProblem) problems.get(i);
194                         retVal[i] = new ProblemAdapter(problem);
195                 }
196                 return retVal;
197         }
198
199         /*
200          * @see AbstractReconcileStep#getModel()
201          */
202         public IReconcilableModel getModel() {
203                 return styleSheetAdapter;
204         }
205
206         // Private Methods Implementation ------------------------------------------
207
208         /**
209          * Retrieve the style sheet associated with the editor input.
210          */
211         private IStyleSheet getStyleSheet() {
212                 IDocumentProvider documentProvider = editor.getDocumentProvider();
213                 if (documentProvider instanceof CssDocumentProvider) {
214                         CssDocumentProvider cssDocumentProvider = (CssDocumentProvider)
215                                 documentProvider;
216                         return cssDocumentProvider.getStyleSheet(editor.getEditorInput());
217                 }
218                 return null;
219         }
220
221 }