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 / CssReconcilingStrategy.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: CssReconcilingStrategy.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.lang.reflect.InvocationTargetException;
17 import java.util.Iterator;
18
19 import net.sourceforge.phpeclipse.css.ui.CssUI;
20
21 import org.eclipse.core.runtime.IProgressMonitor;
22 import org.eclipse.jface.operation.IRunnableWithProgress;
23 import org.eclipse.jface.text.IDocument;
24 import org.eclipse.jface.text.IRegion;
25 import org.eclipse.jface.text.Position;
26 import org.eclipse.jface.text.reconciler.DirtyRegion;
27 import org.eclipse.jface.text.reconciler.IReconcileResult;
28 import org.eclipse.jface.text.reconciler.IReconcileStep;
29 import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
30 import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
31 import org.eclipse.jface.text.source.Annotation;
32 import org.eclipse.jface.text.source.IAnnotationModel;
33 import org.eclipse.ui.IEditorInput;
34 import org.eclipse.ui.actions.WorkspaceModifyOperation;
35 import org.eclipse.ui.texteditor.ITextEditor;
36
37
38 /**
39  * Reconciling strategy for CSS style sheets. This class is responsible for 
40  * keeping the parsed model in sync with the text.
41  */
42 public class CssReconcilingStrategy
43         implements IReconcilingStrategy, IReconcilingStrategyExtension {
44
45         // Instance Variables ------------------------------------------------------
46
47         /**
48          * The associated text editor.
49          */
50         private ITextEditor editor;
51
52         /**
53          * A progress monitor that should be used for long-running operations.
54          */
55         IProgressMonitor progressMonitor;
56
57         /**
58          * The first (and only) reconcile step is the parsing of the style sheet.
59          */
60         private IReconcileStep firstStep;
61
62         // Constructors ------------------------------------------------------------
63
64         public CssReconcilingStrategy(ITextEditor editor) {
65                 this.editor = editor;
66                 firstStep = new CssReconcileStep(editor);
67         }
68
69         // IReconcilingStrategy Implementation -------------------------------------
70
71         /**
72          * @see IReconcilingStrategy#reconcile(DirtyRegion, IRegion)
73          */
74         public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
75                 removeTemporaryAnnotations();
76                 process(firstStep.reconcile(dirtyRegion, subRegion));
77         }
78
79         /**
80          * @see IReconcilingStrategy#reconcile(IRegion)
81          */
82         public void reconcile(IRegion partition) {
83                 removeTemporaryAnnotations();
84                 process(firstStep.reconcile(partition));
85         }
86
87         /**
88          * @see IReconcilingStrategy#setDocument(IDocument)
89          */
90         public void setDocument(IDocument document) {
91                 // FIXME
92                 firstStep.setInputModel(null); //new DocumentAdapter(document);
93         }
94
95         // IReconcilingStrategyExtension Implementation ----------------------------
96
97         /**
98          * @see IReconcilingStrategyExtension#initialReconcile()
99          */
100         public void initialReconcile() {
101                 process(firstStep.reconcile(null));
102         }
103
104         /**
105          * @see IReconcilingStrategyExtension#setProgressMonitor(IProgressMonitor)
106          */
107         public void setProgressMonitor(IProgressMonitor monitor) {
108                 firstStep.setProgressMonitor(monitor);
109                 progressMonitor = monitor;
110         }
111
112         // Private Methods ---------------------------------------------------------
113
114         /**
115          * Returns the annotation model for the editor input.
116          * 
117          * @return the annotation model
118          */
119         IAnnotationModel getAnnotationModel()  {
120                 IEditorInput input = editor.getEditorInput();
121                 return editor.getDocumentProvider().getAnnotationModel(input);
122         }
123
124         /**
125          * Adds results of the reconcilation to the annotation model.
126          */
127         private void process(final IReconcileResult[] results) {
128                 if (results == null) {
129                         return;
130                 }
131
132                 IRunnableWithProgress runnable = new WorkspaceModifyOperation() {
133                         protected void execute(IProgressMonitor monitor) {
134                                 for (int i = 0; i < results.length; i++) {
135                                         if ((progressMonitor != null)
136                                                         && (progressMonitor.isCanceled())) {
137                                                 return;
138                                         }
139
140                                         if (!(results[i] instanceof AnnotationAdapter)) {
141                                                 continue;
142                                         }
143
144                                         AnnotationAdapter result = (AnnotationAdapter) results[i];
145                                         Position pos = result.getPosition();
146                                         Annotation annotation = result.createAnnotation();
147                                         getAnnotationModel().addAnnotation(annotation, pos);
148                                 }
149                         }
150                 };
151
152                 try {
153                         runnable.run(null);
154                 } catch (InvocationTargetException e) {
155                         CssUI.log(e);
156                 } catch (InterruptedException e) {
157                         CssUI.log(e);
158                 }
159
160                 if (editor instanceof IReconcilingParticipant) {
161                         ((IReconcilingParticipant) editor).reconciled();
162                 }
163         }
164
165         /*
166          * TODO A "real" implementation must be smarter, i.e. don't remove and add
167          *      the annotations which are the same.
168          */ 
169         private void removeTemporaryAnnotations() {
170                 Iterator i = getAnnotationModel().getAnnotationIterator();
171                 while (i.hasNext())  {
172                         Annotation annotation = (Annotation) i.next();
173                         if (!annotation.isPersistent()) {
174                                 getAnnotationModel().removeAnnotation(annotation);
175                         }
176                 }
177         }
178 }