blob: 3d992214a389f454d9ba067391035846f3662428 [file] [log] [blame]
david_williamsb1f75052005-02-18 00:25:37 +00001package org.eclipse.wst.css.ui.internal.projection;
2
3import org.eclipse.core.runtime.Platform;
4import org.eclipse.jface.text.IDocument;
amywu91c25662006-06-14 05:08:57 +00005import org.eclipse.jface.text.ITextInputListener;
david_williamsb1f75052005-02-18 00:25:37 +00006import org.eclipse.jface.text.source.projection.IProjectionListener;
7import org.eclipse.jface.text.source.projection.ProjectionViewer;
david_williams63219a22005-04-10 01:59:51 +00008import org.eclipse.wst.css.core.internal.provisional.document.ICSSDocument;
9import org.eclipse.wst.css.core.internal.provisional.document.ICSSModel;
david_williamsb5d05632006-02-27 09:24:00 +000010import org.eclipse.wst.sse.core.StructuredModelManager;
david_williamsc9113882005-04-09 03:19:38 +000011import org.eclipse.wst.sse.core.internal.model.FactoryRegistry;
amywu91c25662006-06-14 05:08:57 +000012import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
david_williams4ad020f2005-04-18 08:00:30 +000013import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
14import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
david_williamsb1f75052005-02-18 00:25:37 +000015import org.eclipse.wst.sse.ui.internal.projection.IStructuredTextFoldingProvider;
16
17/**
18 * Updates the projection model of a structured model for CSS.
19 */
amywu91c25662006-06-14 05:08:57 +000020public class StructuredTextFoldingProviderCSS implements IStructuredTextFoldingProvider, IProjectionListener, ITextInputListener {
david_williamsb1f75052005-02-18 00:25:37 +000021 private final static boolean debugProjectionPerf = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.css.ui/projectionperf")); //$NON-NLS-1$ //$NON-NLS-2$\
22
23 private IDocument fDocument;
24 private ProjectionViewer fViewer;
amywu91c25662006-06-14 05:08:57 +000025 private boolean fProjectionNeedsToBeEnabled = false;
david_williamsb1f75052005-02-18 00:25:37 +000026
27 /**
28 * Just add adapter to top stylesheet node. This adapter will track
29 * children addition/deletion.
30 */
31 private void addAllAdapters() {
32 long start = System.currentTimeMillis();
33
amywu91c25662006-06-14 05:08:57 +000034 if (fDocument != null) {
35 IStructuredModel sModel = null;
36 try {
37 sModel = StructuredModelManager.getModelManager().getExistingModelForRead(fDocument);
38 if (sModel instanceof ICSSModel) {
39 ICSSModel cssModel = (ICSSModel) sModel;
40 ICSSDocument cssDoc = cssModel.getDocument();
41 if (cssDoc instanceof INodeNotifier) {
42 INodeNotifier notifier = (INodeNotifier) cssDoc;
43 ProjectionModelNodeAdapterCSS adapter = (ProjectionModelNodeAdapterCSS) notifier.getExistingAdapter(ProjectionModelNodeAdapterCSS.class);
44 if (adapter != null) {
45 adapter.updateAdapter(cssDoc, fViewer);
46 }
47 else {
48 // just call getadapter so the adapter is created
49 // and
50 // automatically initialized
51 notifier.getAdapterFor(ProjectionModelNodeAdapterCSS.class);
52 }
david_williamsb1f75052005-02-18 00:25:37 +000053 }
54 }
55 }
amywu91c25662006-06-14 05:08:57 +000056 finally {
57 if (sModel != null) {
58 sModel.releaseFromRead();
59 }
david_williamsb1f75052005-02-18 00:25:37 +000060 }
61 }
62
amywu91c25662006-06-14 05:08:57 +000063 if (debugProjectionPerf) {
64 long end = System.currentTimeMillis();
david_williams5bd06bc2005-04-08 19:03:00 +000065 System.out.println("StructuredTextFoldingProviderCSS.addAllAdapters: " + (end - start)); //$NON-NLS-1$
amywu91c25662006-06-14 05:08:57 +000066 }
david_williamsb1f75052005-02-18 00:25:37 +000067 }
68
69 /**
70 * Get the ProjectionModelNodeAdapterFactoryCSS to use with this provider.
71 *
72 * @return ProjectionModelNodeAdapterFactoryCSS
73 */
74 private ProjectionModelNodeAdapterFactoryCSS getAdapterFactory(boolean createIfNeeded) {
75 ProjectionModelNodeAdapterFactoryCSS factory = null;
amywu91c25662006-06-14 05:08:57 +000076 if (fDocument != null) {
77 IStructuredModel sModel = null;
78 try {
79 sModel = StructuredModelManager.getModelManager().getExistingModelForRead(fDocument);
80 if (sModel != null) {
81 FactoryRegistry factoryRegistry = sModel.getFactoryRegistry();
david_williamsb1f75052005-02-18 00:25:37 +000082
amywu91c25662006-06-14 05:08:57 +000083 // getting the projectionmodelnodeadapter for the first
84 // time
85 // so do some initializing
86 if (!factoryRegistry.contains(ProjectionModelNodeAdapterCSS.class) && createIfNeeded) {
87 ProjectionModelNodeAdapterFactoryCSS newFactory = new ProjectionModelNodeAdapterFactoryCSS();
david_williamsb1f75052005-02-18 00:25:37 +000088
amywu91c25662006-06-14 05:08:57 +000089 // add factory to factory registry
90 factoryRegistry.addFactory(newFactory);
91 }
92
93 // try and get the factory
94 factory = (ProjectionModelNodeAdapterFactoryCSS) factoryRegistry.getFactoryFor(ProjectionModelNodeAdapterCSS.class);
david_williamsb1f75052005-02-18 00:25:37 +000095 }
david_williamsb1f75052005-02-18 00:25:37 +000096 }
amywu91c25662006-06-14 05:08:57 +000097 finally {
98 if (sModel != null)
99 sModel.releaseFromRead();
100 }
david_williamsb1f75052005-02-18 00:25:37 +0000101 }
102 return factory;
103 }
104
105 /**
106 * Initialize this provider with the correct document. Assumes projection
107 * is enabled. (otherwise, only install would have been called)
108 */
109 public void initialize() {
110 if (!isInstalled())
111 return;
112
amywu91c25662006-06-14 05:08:57 +0000113 // clear out old info
114 projectionDisabled();
david_williamsb1f75052005-02-18 00:25:37 +0000115
david_williamsb1f75052005-02-18 00:25:37 +0000116 fDocument = fViewer.getDocument();
117
amywu91c25662006-06-14 05:08:57 +0000118 // set projection viewer on new document's adapter factory
119 if (fViewer.getProjectionAnnotationModel() != null) {
120 ProjectionModelNodeAdapterFactoryCSS factory = getAdapterFactory(true);
david_williamsb1f75052005-02-18 00:25:37 +0000121 if (factory != null) {
amywu91c25662006-06-14 05:08:57 +0000122 factory.addProjectionViewer(fViewer);
david_williamsb1f75052005-02-18 00:25:37 +0000123 }
124
125 addAllAdapters();
126 }
amywu91c25662006-06-14 05:08:57 +0000127 fProjectionNeedsToBeEnabled = false;
david_williamsb1f75052005-02-18 00:25:37 +0000128 }
129
130 /**
131 * Associate a ProjectionViewer with this IStructuredTextFoldingProvider
132 *
amywu91c25662006-06-14 05:08:57 +0000133 * @param viewer -
134 * assumes not null
david_williamsb1f75052005-02-18 00:25:37 +0000135 */
136 public void install(ProjectionViewer viewer) {
137 // uninstall before trying to install new viewer
138 if (isInstalled()) {
139 uninstall();
140 }
141 fViewer = viewer;
142 fViewer.addProjectionListener(this);
amywu91c25662006-06-14 05:08:57 +0000143 fViewer.addTextInputListener(this);
david_williamsb1f75052005-02-18 00:25:37 +0000144 }
145
146 private boolean isInstalled() {
147 return fViewer != null;
148 }
149
150 public void projectionDisabled() {
151 ProjectionModelNodeAdapterFactoryCSS factory = getAdapterFactory(false);
152 if (factory != null) {
amywu91c25662006-06-14 05:08:57 +0000153 factory.removeProjectionViewer(fViewer);
david_williamsb1f75052005-02-18 00:25:37 +0000154 }
155
amywu91c25662006-06-14 05:08:57 +0000156 // clear out all annotations
157 if (fViewer.getProjectionAnnotationModel() != null)
158 fViewer.getProjectionAnnotationModel().removeAllAnnotations();
159
160 removeAllAdapters();
161
david_williamsb1f75052005-02-18 00:25:37 +0000162 fDocument = null;
amywu91c25662006-06-14 05:08:57 +0000163 fProjectionNeedsToBeEnabled = false;
david_williamsb1f75052005-02-18 00:25:37 +0000164 }
165
166 public void projectionEnabled() {
167 initialize();
168 }
169
170 /**
amywu91c25662006-06-14 05:08:57 +0000171 * Removes adapter from top stylesheet node
172 */
173 private void removeAllAdapters() {
174 long start = System.currentTimeMillis();
175
176 if (fDocument != null) {
177 IStructuredModel sModel = null;
178 try {
179 sModel = StructuredModelManager.getModelManager().getExistingModelForRead(fDocument);
180 if (sModel instanceof ICSSModel) {
181 ICSSModel cssModel = (ICSSModel) sModel;
182 ICSSDocument cssDoc = cssModel.getDocument();
183 if (cssDoc instanceof INodeNotifier) {
184 INodeNotifier notifier = (INodeNotifier) cssDoc;
185 INodeAdapter adapter = notifier.getExistingAdapter(ProjectionModelNodeAdapterCSS.class);
186 if (adapter != null) {
187 notifier.removeAdapter(adapter);
188 }
189 }
190 }
191 }
192 finally {
193 if (sModel != null) {
194 sModel.releaseFromRead();
195 }
196 }
197 }
198
199 if (debugProjectionPerf) {
200 long end = System.currentTimeMillis();
201 System.out.println("StructuredTextFoldingProviderCSS.addAllAdapters: " + (end - start)); //$NON-NLS-1$
202 }
203 }
204
205 public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
206 // if folding is enabled and new document is going to be a totally
207 // different document, disable projection
208 if (fDocument != null && fDocument != newInput) {
209 // disable projection and disconnect everything
210 projectionDisabled();
211 fProjectionNeedsToBeEnabled = true;
212 }
213 }
214
215 public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
216 // if projection was previously enabled before input document changed
217 // and new document is different than old document
218 if (fProjectionNeedsToBeEnabled && fDocument == null && newInput != null) {
219 projectionEnabled();
220 fProjectionNeedsToBeEnabled = false;
221 }
222 }
223
224 /**
david_williamsb1f75052005-02-18 00:25:37 +0000225 * Disconnect this IStructuredTextFoldingProvider from projection viewer
226 */
227 public void uninstall() {
228 if (isInstalled()) {
229 projectionDisabled();
230
231 fViewer.removeProjectionListener(this);
amywu91c25662006-06-14 05:08:57 +0000232 fViewer.removeTextInputListener(this);
david_williamsb1f75052005-02-18 00:25:37 +0000233 fViewer = null;
234 }
235 }
236}