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