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