Mercurial > projects > dwt2
comparison org.eclipse.jface.text/src/org/eclipse/jface/text/formatter/MultiPassContentFormatter.d @ 12:bc29606a740c
Added dwt-addons in original directory structure of eclipse.org
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 14 Mar 2009 18:23:29 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
11:43904fec5dca | 12:bc29606a740c |
---|---|
1 /******************************************************************************* | |
2 * Copyright (c) 2000, 2006 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
12 *******************************************************************************/ | |
13 | |
14 | |
15 module org.eclipse.jface.text.formatter.MultiPassContentFormatter; | |
16 | |
17 import org.eclipse.jface.text.formatter.ContextBasedFormattingStrategy; // packageimport | |
18 import org.eclipse.jface.text.formatter.FormattingContext; // packageimport | |
19 import org.eclipse.jface.text.formatter.IFormattingStrategy; // packageimport | |
20 import org.eclipse.jface.text.formatter.IContentFormatterExtension; // packageimport | |
21 import org.eclipse.jface.text.formatter.IFormattingStrategyExtension; // packageimport | |
22 import org.eclipse.jface.text.formatter.IContentFormatter; // packageimport | |
23 import org.eclipse.jface.text.formatter.FormattingContextProperties; // packageimport | |
24 import org.eclipse.jface.text.formatter.ContentFormatter; // packageimport | |
25 import org.eclipse.jface.text.formatter.IFormattingContext; // packageimport | |
26 | |
27 import java.lang.all; | |
28 import java.util.Map; | |
29 import java.util.HashMap; | |
30 import java.util.Set; | |
31 | |
32 import org.eclipse.core.runtime.Assert; | |
33 import org.eclipse.jface.text.BadLocationException; | |
34 import org.eclipse.jface.text.DefaultPositionUpdater; | |
35 import org.eclipse.jface.text.IDocument; | |
36 import org.eclipse.jface.text.IRegion; | |
37 import org.eclipse.jface.text.ITypedRegion; | |
38 import org.eclipse.jface.text.TextUtilities; | |
39 import org.eclipse.jface.text.TypedPosition; | |
40 | |
41 /** | |
42 * Content formatter for edit-based formatting strategies. | |
43 * <p> | |
44 * Two kinds of formatting strategies can be registered with this formatter: | |
45 * <ul> | |
46 * <li>one master formatting strategy for the default content type</li> | |
47 * <li>one formatting strategy for each non-default content type</li> | |
48 * </ul> | |
49 * The master formatting strategy always formats the whole region to be | |
50 * formatted in the first pass. In a second pass, all partitions of the region | |
51 * to be formatted that are not of master content type are formatted using the | |
52 * slave formatting strategy registered for the underlying content type. All | |
53 * formatting strategies must implement {@link IFormattingStrategyExtension}. | |
54 * <p> | |
55 * Regions to be formatted with the master formatting strategy always have | |
56 * an offset aligned to the line start. Regions to be formatted with slave formatting | |
57 * strategies are aligned on partition boundaries. | |
58 * | |
59 * @see IFormattingStrategyExtension | |
60 * @since 3.0 | |
61 */ | |
62 public class MultiPassContentFormatter : IContentFormatter, IContentFormatterExtension { | |
63 | |
64 /** | |
65 * Position updater that shifts otherwise deleted positions to the next | |
66 * non-whitespace character. The length of the positions are truncated to | |
67 * one if the position was shifted. | |
68 */ | |
69 protected class NonDeletingPositionUpdater : DefaultPositionUpdater { | |
70 | |
71 /** | |
72 * Creates a new non-deleting position updater. | |
73 * | |
74 * @param category The position category to update its positions | |
75 */ | |
76 public this(String category) { | |
77 super(category); | |
78 } | |
79 | |
80 /* | |
81 * @see org.eclipse.jface.text.DefaultPositionUpdater#notDeleted() | |
82 */ | |
83 protected final bool notDeleted() { | |
84 | |
85 if (fOffset < fPosition.offset && (fPosition.offset + fPosition.length < fOffset + fLength)) { | |
86 | |
87 int offset= fOffset + fLength; | |
88 if (offset < fDocument.getLength()) { | |
89 | |
90 try { | |
91 | |
92 bool moved= false; | |
93 char character= fDocument.getChar(offset); | |
94 | |
95 while (offset < fDocument.getLength() && Character.isWhitespace(character)) { | |
96 | |
97 moved= true; | |
98 character= fDocument.getChar(offset++); | |
99 } | |
100 | |
101 if (moved) | |
102 offset--; | |
103 | |
104 } catch (BadLocationException exception) { | |
105 // Can not happen | |
106 } | |
107 | |
108 fPosition.offset= offset; | |
109 fPosition.length= 0; | |
110 } | |
111 } | |
112 return true; | |
113 } | |
114 } | |
115 | |
116 /** The master formatting strategy */ | |
117 private IFormattingStrategyExtension fMaster= null; | |
118 /** The partitioning of this content formatter */ | |
119 private const String fPartitioning; | |
120 /** The slave formatting strategies */ | |
121 private const Map fSlaves; | |
122 /** The default content type */ | |
123 private const String fType; | |
124 | |
125 /** | |
126 * Creates a new content formatter. | |
127 * | |
128 * @param partitioning the document partitioning for this formatter | |
129 * @param type the default content type | |
130 */ | |
131 public this(String partitioning, String type) { | |
132 fSlaves= new HashMap(); | |
133 | |
134 fPartitioning= partitioning; | |
135 fType= type; | |
136 } | |
137 | |
138 /* | |
139 * @see org.eclipse.jface.text.formatter.IContentFormatterExtension#format(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.formatter.IFormattingContext) | |
140 */ | |
141 public final void format(IDocument medium, IFormattingContext context) { | |
142 | |
143 context.setProperty(stringcast(FormattingContextProperties.CONTEXT_MEDIUM), cast(Object)medium); | |
144 | |
145 final Boolean document= cast(Boolean)context.getProperty(stringcast(FormattingContextProperties.CONTEXT_DOCUMENT)); | |
146 if (document is null || !document.booleanValue()) { | |
147 | |
148 final IRegion region= cast(IRegion)context.getProperty(stringcast(FormattingContextProperties.CONTEXT_REGION)); | |
149 if (region !is null) { | |
150 try { | |
151 formatMaster(context, medium, region.getOffset(), region.getLength()); | |
152 } finally { | |
153 formatSlaves(context, medium, region.getOffset(), region.getLength()); | |
154 } | |
155 } | |
156 } else { | |
157 try { | |
158 formatMaster(context, medium, 0, medium.getLength()); | |
159 } finally { | |
160 formatSlaves(context, medium, 0, medium.getLength()); | |
161 } | |
162 } | |
163 } | |
164 | |
165 /* | |
166 * @see org.eclipse.jface.text.formatter.IContentFormatter#format(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IRegion) | |
167 */ | |
168 public final void format(IDocument medium, IRegion region) { | |
169 | |
170 final FormattingContext context= new FormattingContext(); | |
171 | |
172 context.setProperty(stringcast(FormattingContextProperties.CONTEXT_DOCUMENT), Boolean.FALSE); | |
173 context.setProperty(stringcast(FormattingContextProperties.CONTEXT_REGION), cast(Object)region); | |
174 | |
175 format(medium, context); | |
176 } | |
177 | |
178 /** | |
179 * Formats the document specified in the formatting context with the master | |
180 * formatting strategy. | |
181 * <p> | |
182 * The master formatting strategy covers all regions of the document. The | |
183 * offset of the region to be formatted is aligned on line start boundaries, | |
184 * whereas the end index of the region remains the same. For this formatting | |
185 * type the document partitioning is not taken into account. | |
186 * | |
187 * @param context The formatting context to use | |
188 * @param document The document to operate on | |
189 * @param offset The offset of the region to format | |
190 * @param length The length of the region to format | |
191 */ | |
192 protected void formatMaster(IFormattingContext context, IDocument document, int offset, int length) { | |
193 | |
194 try { | |
195 | |
196 final int delta= offset - document.getLineInformationOfOffset(offset).getOffset(); | |
197 offset -= delta; | |
198 length += delta; | |
199 | |
200 } catch (BadLocationException exception) { | |
201 // Do nothing | |
202 } | |
203 | |
204 if (fMaster !is null) { | |
205 | |
206 context.setProperty(stringcast(FormattingContextProperties.CONTEXT_PARTITION), new TypedPosition(offset, length, fType)); | |
207 | |
208 fMaster.formatterStarts(context); | |
209 fMaster.format(); | |
210 fMaster.formatterStops(); | |
211 } | |
212 } | |
213 | |
214 /** | |
215 * Formats the document specified in the formatting context with the | |
216 * formatting strategy registered for the content type. | |
217 * <p> | |
218 * For this formatting type only slave strategies are used. The region to be | |
219 * formatted is aligned on partition boundaries of the underlying content | |
220 * type. The exact formatting strategy is determined by the underlying | |
221 * content type of the document partitioning. | |
222 * | |
223 * @param context The formatting context to use | |
224 * @param document The document to operate on | |
225 * @param offset The offset of the region to format | |
226 * @param length The length of the region to format | |
227 * @param type The content type of the region to format | |
228 */ | |
229 protected void formatSlave(IFormattingContext context, IDocument document, int offset, int length, String type) { | |
230 | |
231 final IFormattingStrategyExtension strategy= cast(IFormattingStrategyExtension)fSlaves.get(type); | |
232 if (strategy !is null) { | |
233 | |
234 context.setProperty(stringcast(FormattingContextProperties.CONTEXT_PARTITION), new TypedPosition(offset, length, type)); | |
235 | |
236 strategy.formatterStarts(context); | |
237 strategy.format(); | |
238 strategy.formatterStops(); | |
239 } | |
240 } | |
241 | |
242 /** | |
243 * Formats the document specified in the formatting context with the slave | |
244 * formatting strategies. | |
245 * <p> | |
246 * For each content type of the region to be formatted in the document | |
247 * partitioning, the registered slave formatting strategy is used to format | |
248 * that particular region. The region to be formatted is aligned on | |
249 * partition boundaries of the underlying content type. If the content type | |
250 * is the document's default content type, nothing happens. | |
251 * | |
252 * @param context The formatting context to use | |
253 * @param document The document to operate on | |
254 * @param offset The offset of the region to format | |
255 * @param length The length of the region to format | |
256 */ | |
257 protected void formatSlaves(IFormattingContext context, IDocument document, int offset, int length) { | |
258 | |
259 Map partitioners= new HashMap(0); | |
260 try { | |
261 | |
262 final ITypedRegion[] partitions= TextUtilities.computePartitioning(document, fPartitioning, offset, length, false); | |
263 | |
264 if (!fType.equals(partitions[0].getType())) | |
265 partitions[0]= TextUtilities.getPartition(document, fPartitioning, partitions[0].getOffset(), false); | |
266 | |
267 if (partitions.length > 1) { | |
268 | |
269 if (!fType.equals(partitions[partitions.length - 1].getType())) | |
270 partitions[partitions.length - 1]= TextUtilities.getPartition(document, fPartitioning, partitions[partitions.length - 1].getOffset(), false); | |
271 } | |
272 | |
273 String type= null; | |
274 ITypedRegion partition= null; | |
275 | |
276 partitioners= TextUtilities.removeDocumentPartitioners(document); | |
277 | |
278 for (int index= partitions.length - 1; index >= 0; index--) { | |
279 | |
280 partition= partitions[index]; | |
281 type= partition.getType(); | |
282 | |
283 if (!fType.equals(type)) | |
284 formatSlave(context, document, partition.getOffset(), partition.getLength(), type); | |
285 } | |
286 | |
287 } catch (BadLocationException exception) { | |
288 // Should not happen | |
289 } finally { | |
290 TextUtilities.addDocumentPartitioners(document, partitioners); | |
291 } | |
292 } | |
293 | |
294 /* | |
295 * @see org.eclipse.jface.text.formatter.IContentFormatter#getFormattingStrategy(java.lang.String) | |
296 */ | |
297 public final IFormattingStrategy getFormattingStrategy(String type) { | |
298 return null; | |
299 } | |
300 | |
301 /** | |
302 * Registers a master formatting strategy. | |
303 * <p> | |
304 * The strategy may already be registered with a certain content type as | |
305 * slave strategy. The master strategy is registered for the default content | |
306 * type of documents. If a master strategy has already been registered, it | |
307 * is overridden by the new one. | |
308 * | |
309 * @param strategy The master formatting strategy, must implement | |
310 * {@link IFormattingStrategyExtension} | |
311 */ | |
312 public final void setMasterStrategy(IFormattingStrategy strategy) { | |
313 Assert.isTrue( null !is cast(IFormattingStrategyExtension)strategy ); | |
314 fMaster= cast(IFormattingStrategyExtension) strategy; | |
315 } | |
316 | |
317 /** | |
318 * Registers a slave formatting strategy for a certain content type. | |
319 * <p> | |
320 * The strategy may already be registered as master strategy. An | |
321 * already registered slave strategy for the specified content type | |
322 * will be replaced. However, the same strategy may be registered with | |
323 * several content types. Slave strategies cannot be registered for the | |
324 * default content type of documents. | |
325 * | |
326 * @param strategy The slave formatting strategy | |
327 * @param type The content type to register this strategy with, | |
328 * must implement {@link IFormattingStrategyExtension} | |
329 */ | |
330 public final void setSlaveStrategy(IFormattingStrategy strategy, String type) { | |
331 Assert.isTrue( null !is cast(IFormattingStrategyExtension)strategy ); | |
332 if (!fType.equals(type)) | |
333 fSlaves.put(type, cast(Object)strategy); | |
334 } | |
335 } |