comparison org.eclipse.jface.text/src/org/eclipse/jface/text/JFaceTextUtil.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) 2006, 2008 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 module org.eclipse.jface.text.JFaceTextUtil;
14
15 import org.eclipse.jface.text.IDocumentPartitioningListener; // packageimport
16 import org.eclipse.jface.text.DefaultTextHover; // packageimport
17 import org.eclipse.jface.text.AbstractInformationControl; // packageimport
18 import org.eclipse.jface.text.TextUtilities; // packageimport
19 import org.eclipse.jface.text.IInformationControlCreatorExtension; // packageimport
20 import org.eclipse.jface.text.AbstractInformationControlManager; // packageimport
21 import org.eclipse.jface.text.ITextViewerExtension2; // packageimport
22 import org.eclipse.jface.text.IDocumentPartitioner; // packageimport
23 import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy; // packageimport
24 import org.eclipse.jface.text.ITextSelection; // packageimport
25 import org.eclipse.jface.text.Document; // packageimport
26 import org.eclipse.jface.text.FindReplaceDocumentAdapterContentProposalProvider; // packageimport
27 import org.eclipse.jface.text.ITextListener; // packageimport
28 import org.eclipse.jface.text.BadPartitioningException; // packageimport
29 import org.eclipse.jface.text.ITextViewerExtension5; // packageimport
30 import org.eclipse.jface.text.IDocumentPartitionerExtension3; // packageimport
31 import org.eclipse.jface.text.IUndoManager; // packageimport
32 import org.eclipse.jface.text.ITextHoverExtension2; // packageimport
33 import org.eclipse.jface.text.IRepairableDocument; // packageimport
34 import org.eclipse.jface.text.IRewriteTarget; // packageimport
35 import org.eclipse.jface.text.DefaultPositionUpdater; // packageimport
36 import org.eclipse.jface.text.RewriteSessionEditProcessor; // packageimport
37 import org.eclipse.jface.text.TextViewerHoverManager; // packageimport
38 import org.eclipse.jface.text.DocumentRewriteSession; // packageimport
39 import org.eclipse.jface.text.TextViewer; // packageimport
40 import org.eclipse.jface.text.ITextViewerExtension8; // packageimport
41 import org.eclipse.jface.text.RegExMessages; // packageimport
42 import org.eclipse.jface.text.IDelayedInputChangeProvider; // packageimport
43 import org.eclipse.jface.text.ITextOperationTargetExtension; // packageimport
44 import org.eclipse.jface.text.IWidgetTokenOwner; // packageimport
45 import org.eclipse.jface.text.IViewportListener; // packageimport
46 import org.eclipse.jface.text.GapTextStore; // packageimport
47 import org.eclipse.jface.text.MarkSelection; // packageimport
48 import org.eclipse.jface.text.IDocumentPartitioningListenerExtension; // packageimport
49 import org.eclipse.jface.text.IDocumentAdapterExtension; // packageimport
50 import org.eclipse.jface.text.IInformationControlExtension; // packageimport
51 import org.eclipse.jface.text.IDocumentPartitioningListenerExtension2; // packageimport
52 import org.eclipse.jface.text.DefaultDocumentAdapter; // packageimport
53 import org.eclipse.jface.text.ITextViewerExtension3; // packageimport
54 import org.eclipse.jface.text.IInformationControlCreator; // packageimport
55 import org.eclipse.jface.text.TypedRegion; // packageimport
56 import org.eclipse.jface.text.ISynchronizable; // packageimport
57 import org.eclipse.jface.text.IMarkRegionTarget; // packageimport
58 import org.eclipse.jface.text.TextViewerUndoManager; // packageimport
59 import org.eclipse.jface.text.IRegion; // packageimport
60 import org.eclipse.jface.text.IInformationControlExtension2; // packageimport
61 import org.eclipse.jface.text.IDocumentExtension4; // packageimport
62 import org.eclipse.jface.text.IDocumentExtension2; // packageimport
63 import org.eclipse.jface.text.IDocumentPartitionerExtension2; // packageimport
64 import org.eclipse.jface.text.Assert; // packageimport
65 import org.eclipse.jface.text.DefaultInformationControl; // packageimport
66 import org.eclipse.jface.text.IWidgetTokenOwnerExtension; // packageimport
67 import org.eclipse.jface.text.DocumentClone; // packageimport
68 import org.eclipse.jface.text.DefaultUndoManager; // packageimport
69 import org.eclipse.jface.text.IFindReplaceTarget; // packageimport
70 import org.eclipse.jface.text.IAutoEditStrategy; // packageimport
71 import org.eclipse.jface.text.ILineTrackerExtension; // packageimport
72 import org.eclipse.jface.text.IUndoManagerExtension; // packageimport
73 import org.eclipse.jface.text.TextSelection; // packageimport
74 import org.eclipse.jface.text.DefaultAutoIndentStrategy; // packageimport
75 import org.eclipse.jface.text.IAutoIndentStrategy; // packageimport
76 import org.eclipse.jface.text.IPainter; // packageimport
77 import org.eclipse.jface.text.IInformationControl; // packageimport
78 import org.eclipse.jface.text.IInformationControlExtension3; // packageimport
79 import org.eclipse.jface.text.ITextViewerExtension6; // packageimport
80 import org.eclipse.jface.text.IInformationControlExtension4; // packageimport
81 import org.eclipse.jface.text.DefaultLineTracker; // packageimport
82 import org.eclipse.jface.text.IDocumentInformationMappingExtension; // packageimport
83 import org.eclipse.jface.text.IRepairableDocumentExtension; // packageimport
84 import org.eclipse.jface.text.ITextHover; // packageimport
85 import org.eclipse.jface.text.FindReplaceDocumentAdapter; // packageimport
86 import org.eclipse.jface.text.ILineTracker; // packageimport
87 import org.eclipse.jface.text.Line; // packageimport
88 import org.eclipse.jface.text.ITextViewerExtension; // packageimport
89 import org.eclipse.jface.text.IDocumentAdapter; // packageimport
90 import org.eclipse.jface.text.TextEvent; // packageimport
91 import org.eclipse.jface.text.BadLocationException; // packageimport
92 import org.eclipse.jface.text.AbstractDocument; // packageimport
93 import org.eclipse.jface.text.AbstractLineTracker; // packageimport
94 import org.eclipse.jface.text.TreeLineTracker; // packageimport
95 import org.eclipse.jface.text.ITextPresentationListener; // packageimport
96 import org.eclipse.jface.text.Region; // packageimport
97 import org.eclipse.jface.text.ITextViewer; // packageimport
98 import org.eclipse.jface.text.IDocumentInformationMapping; // packageimport
99 import org.eclipse.jface.text.MarginPainter; // packageimport
100 import org.eclipse.jface.text.IPaintPositionManager; // packageimport
101 import org.eclipse.jface.text.TextPresentation; // packageimport
102 import org.eclipse.jface.text.IFindReplaceTargetExtension; // packageimport
103 import org.eclipse.jface.text.ISlaveDocumentManagerExtension; // packageimport
104 import org.eclipse.jface.text.ISelectionValidator; // packageimport
105 import org.eclipse.jface.text.IDocumentExtension; // packageimport
106 import org.eclipse.jface.text.PropagatingFontFieldEditor; // packageimport
107 import org.eclipse.jface.text.ConfigurableLineTracker; // packageimport
108 import org.eclipse.jface.text.SlaveDocumentEvent; // packageimport
109 import org.eclipse.jface.text.IDocumentListener; // packageimport
110 import org.eclipse.jface.text.PaintManager; // packageimport
111 import org.eclipse.jface.text.IFindReplaceTargetExtension3; // packageimport
112 import org.eclipse.jface.text.ITextDoubleClickStrategy; // packageimport
113 import org.eclipse.jface.text.IDocumentExtension3; // packageimport
114 import org.eclipse.jface.text.Position; // packageimport
115 import org.eclipse.jface.text.TextMessages; // packageimport
116 import org.eclipse.jface.text.CopyOnWriteTextStore; // packageimport
117 import org.eclipse.jface.text.WhitespaceCharacterPainter; // packageimport
118 import org.eclipse.jface.text.IPositionUpdater; // packageimport
119 import org.eclipse.jface.text.DefaultTextDoubleClickStrategy; // packageimport
120 import org.eclipse.jface.text.ListLineTracker; // packageimport
121 import org.eclipse.jface.text.ITextInputListener; // packageimport
122 import org.eclipse.jface.text.BadPositionCategoryException; // packageimport
123 import org.eclipse.jface.text.IWidgetTokenKeeperExtension; // packageimport
124 import org.eclipse.jface.text.IInputChangedListener; // packageimport
125 import org.eclipse.jface.text.ITextOperationTarget; // packageimport
126 import org.eclipse.jface.text.IDocumentInformationMappingExtension2; // packageimport
127 import org.eclipse.jface.text.ITextViewerExtension7; // packageimport
128 import org.eclipse.jface.text.IInformationControlExtension5; // packageimport
129 import org.eclipse.jface.text.IDocumentRewriteSessionListener; // packageimport
130 import org.eclipse.jface.text.AbstractReusableInformationControlCreator; // packageimport
131 import org.eclipse.jface.text.TabsToSpacesConverter; // packageimport
132 import org.eclipse.jface.text.CursorLinePainter; // packageimport
133 import org.eclipse.jface.text.ITextHoverExtension; // packageimport
134 import org.eclipse.jface.text.IEventConsumer; // packageimport
135 import org.eclipse.jface.text.IDocument; // packageimport
136 import org.eclipse.jface.text.IWidgetTokenKeeper; // packageimport
137 import org.eclipse.jface.text.DocumentCommand; // packageimport
138 import org.eclipse.jface.text.TypedPosition; // packageimport
139 import org.eclipse.jface.text.IEditingSupportRegistry; // packageimport
140 import org.eclipse.jface.text.IDocumentPartitionerExtension; // packageimport
141 import org.eclipse.jface.text.AbstractHoverInformationControlManager; // packageimport
142 import org.eclipse.jface.text.IEditingSupport; // packageimport
143 import org.eclipse.jface.text.IMarkSelection; // packageimport
144 import org.eclipse.jface.text.ISlaveDocumentManager; // packageimport
145 import org.eclipse.jface.text.DocumentEvent; // packageimport
146 import org.eclipse.jface.text.DocumentPartitioningChangedEvent; // packageimport
147 import org.eclipse.jface.text.ITextStore; // packageimport
148 import org.eclipse.jface.text.JFaceTextMessages; // packageimport
149 import org.eclipse.jface.text.DocumentRewriteSessionEvent; // packageimport
150 import org.eclipse.jface.text.SequentialRewriteTextStore; // packageimport
151 import org.eclipse.jface.text.DocumentRewriteSessionType; // packageimport
152 import org.eclipse.jface.text.TextAttribute; // packageimport
153 import org.eclipse.jface.text.ITextViewerExtension4; // packageimport
154 import org.eclipse.jface.text.ITypedRegion; // packageimport
155
156
157 import java.lang.all;
158 import java.util.Set;
159
160
161
162 import org.eclipse.swt.custom.StyledText;
163 import org.eclipse.swt.graphics.GC;
164 import org.eclipse.swt.graphics.Point;
165 import org.eclipse.swt.graphics.Rectangle;
166 import org.eclipse.swt.widgets.Control;
167 import org.eclipse.jface.text.source.ILineRange;
168 import org.eclipse.jface.text.source.LineRange;
169
170 /**
171 * A collection of JFace Text functions.
172 * <p>
173 * This class is neither intended to be instantiated nor subclassed.
174 * </p>
175 *
176 * @since 3.3
177 * @noinstantiate This class is not intended to be instantiated by clients.
178 */
179 public final class JFaceTextUtil {
180
181 private this() {
182 // Do not instantiate
183 }
184
185 /**
186 * Computes the line height for the given line range.
187 *
188 * @param textWidget the <code>StyledText</code> widget
189 * @param startLine the start line
190 * @param endLine the end line (exclusive)
191 * @param lineCount the line count used by the old API
192 * @return the height of all lines starting with <code>startLine</code> and ending above <code>endLime</code>
193 */
194 public static int computeLineHeight(StyledText textWidget, int startLine, int endLine, int lineCount) {
195 return getLinePixel(textWidget, endLine) - getLinePixel(textWidget, startLine);
196 }
197
198 /**
199 * Returns the last fully visible line of the widget. The exact semantics of "last fully visible
200 * line" are:
201 * <ul>
202 * <li>the last line of which the last pixel is visible, if any
203 * <li>otherwise, the only line that is partially visible
204 * </ul>
205 *
206 * @param widget the widget
207 * @return the last fully visible line
208 */
209 public static int getBottomIndex(StyledText widget) {
210 int lastPixel= computeLastVisiblePixel(widget);
211
212 // bottom is in [0 .. lineCount - 1]
213 int bottom= widget.getLineIndex(lastPixel);
214
215 // bottom is the first line - no more checking
216 if (bottom is 0)
217 return bottom;
218
219 int pixel= widget.getLinePixel(bottom);
220 // bottom starts on or before the client area start - bottom is the only visible line
221 if (pixel <= 0)
222 return bottom;
223
224 int offset= widget.getOffsetAtLine(bottom);
225 int height= widget.getLineHeight(offset);
226
227 // bottom is not showing entirely - use the previous line
228 if (pixel + height - 1 > lastPixel)
229 return bottom - 1;
230
231 // bottom is fully visible and its last line is exactly the last pixel
232 return bottom;
233 }
234
235 /**
236 * Returns the index of the first (possibly only partially) visible line of the widget
237 *
238 * @param widget the widget
239 * @return the index of the first line of which a pixel is visible
240 */
241 public static int getPartialTopIndex(StyledText widget) {
242 // see StyledText#getPartialTopIndex()
243 int top= widget.getTopIndex();
244 int pixels= widget.getLinePixel(top);
245
246 // FIXME remove when https://bugs.eclipse.org/bugs/show_bug.cgi?id=123770 is fixed
247 if (pixels is -widget.getLineHeight(widget.getOffsetAtLine(top))) {
248 top++;
249 pixels= 0;
250 }
251
252 if (pixels > 0)
253 top--;
254
255 return top;
256 }
257
258 /**
259 * Returns the index of the last (possibly only partially) visible line of the widget
260 *
261 * @param widget the text widget
262 * @return the index of the last line of which a pixel is visible
263 */
264 public static int getPartialBottomIndex(StyledText widget) {
265 // @see StyledText#getPartialBottomIndex()
266 int lastPixel= computeLastVisiblePixel(widget);
267 int bottom= widget.getLineIndex(lastPixel);
268 return bottom;
269 }
270
271 /**
272 * Returns the last visible pixel in the widget's client area.
273 *
274 * @param widget the widget
275 * @return the last visible pixel in the widget's client area
276 */
277 private static int computeLastVisiblePixel(StyledText widget) {
278 int caHeight= widget.getClientArea().height;
279 int lastPixel= caHeight - 1;
280 // XXX what if there is a margin? can't take trim as this includes the scrollbars which are not part of the client area
281 // if ((textWidget.getStyle() & SWT.BORDER) !is 0)
282 // lastPixel -= 4;
283 return lastPixel;
284 }
285
286 /**
287 * Returns the line index of the first visible model line in the viewer. The line may be only
288 * partially visible.
289 *
290 * @param viewer the text viewer
291 * @return the first line of which a pixel is visible, or -1 for no line
292 */
293 public static int getPartialTopIndex(ITextViewer viewer) {
294 StyledText widget= viewer.getTextWidget();
295 int widgetTop= getPartialTopIndex(widget);
296 return widgetLine2ModelLine(viewer, widgetTop);
297 }
298
299 /**
300 * Returns the last, possibly partially, visible line in the view port.
301 *
302 * @param viewer the text viewer
303 * @return the last, possibly partially, visible line in the view port
304 */
305 public static int getPartialBottomIndex(ITextViewer viewer) {
306 StyledText textWidget= viewer.getTextWidget();
307 int widgetBottom= getPartialBottomIndex(textWidget);
308 return widgetLine2ModelLine(viewer, widgetBottom);
309 }
310
311 /**
312 * Returns the range of lines that is visible in the viewer, including any partially visible
313 * lines.
314 *
315 * @param viewer the viewer
316 * @return the range of lines that is visible in the viewer, <code>null</code> if no lines are
317 * visible
318 */
319 public static ILineRange getVisibleModelLines(ITextViewer viewer) {
320 int top= getPartialTopIndex(viewer);
321 int bottom= getPartialBottomIndex(viewer);
322 if (top is -1 || bottom is -1)
323 return null;
324 return new LineRange(top, bottom - top + 1);
325 }
326
327 /**
328 * Converts a widget line into a model (i.e. {@link IDocument}) line using the
329 * {@link ITextViewerExtension5} if available, otherwise by adapting the widget line to the
330 * viewer's {@link ITextViewer#getVisibleRegion() visible region}.
331 *
332 * @param viewer the viewer
333 * @param widgetLine the widget line to convert.
334 * @return the model line corresponding to <code>widgetLine</code> or -1 to signal that there
335 * is no corresponding model line
336 */
337 public static int widgetLine2ModelLine(ITextViewer viewer, int widgetLine) {
338 int modelLine;
339 if ( cast(ITextViewerExtension5)viewer ) {
340 ITextViewerExtension5 extension= cast(ITextViewerExtension5) viewer;
341 modelLine= extension.widgetLine2ModelLine(widgetLine);
342 } else {
343 try {
344 IRegion r= viewer.getVisibleRegion();
345 IDocument d= viewer.getDocument();
346 modelLine= widgetLine + d.getLineOfOffset(r.getOffset());
347 } catch (BadLocationException x) {
348 modelLine= widgetLine;
349 }
350 }
351 return modelLine;
352 }
353
354 /**
355 * Converts a model (i.e. {@link IDocument}) line into a widget line using the
356 * {@link ITextViewerExtension5} if available, otherwise by adapting the model line to the
357 * viewer's {@link ITextViewer#getVisibleRegion() visible region}.
358 *
359 * @param viewer the viewer
360 * @param modelLine the model line to convert.
361 * @return the widget line corresponding to <code>modelLine</code> or -1 to signal that there
362 * is no corresponding widget line
363 */
364 public static int modelLineToWidgetLine(ITextViewer viewer, int modelLine) {
365 int widgetLine;
366 if ( cast(ITextViewerExtension5)viewer ) {
367 ITextViewerExtension5 extension= cast(ITextViewerExtension5) viewer;
368 widgetLine= extension.modelLine2WidgetLine(modelLine);
369 } else {
370 IRegion region= viewer.getVisibleRegion();
371 IDocument document= viewer.getDocument();
372 try {
373 int visibleStartLine= document.getLineOfOffset(region.getOffset());
374 int visibleEndLine= document.getLineOfOffset(region.getOffset() + region.getLength());
375 if (modelLine < visibleStartLine || modelLine > visibleEndLine)
376 widgetLine= -1;
377 else
378 widgetLine= modelLine - visibleStartLine;
379 } catch (BadLocationException x) {
380 // ignore and return -1
381 widgetLine= -1;
382 }
383 }
384 return widgetLine;
385 }
386
387
388 /**
389 * Returns the number of hidden pixels of the first partially visible line. If there is no
390 * partially visible line, zero is returned.
391 *
392 * @param textWidget the widget
393 * @return the number of hidden pixels of the first partial line, always &gt;= 0
394 */
395 public static int getHiddenTopLinePixels(StyledText textWidget) {
396 int top= getPartialTopIndex(textWidget);
397 return -textWidget.getLinePixel(top);
398 }
399
400 /*
401 * @see StyledText#getLinePixel(int)
402 */
403 public static int getLinePixel(StyledText textWidget, int line) {
404 return textWidget.getLinePixel(line);
405 }
406
407 /*
408 * @see StyledText#getLineIndex(int)
409 */
410 public static int getLineIndex(StyledText textWidget, int y) {
411 int lineIndex= textWidget.getLineIndex(y);
412 return lineIndex;
413 }
414
415 /**
416 * Returns <code>true</code> if the widget displays the entire contents, i.e. it cannot
417 * be vertically scrolled.
418 *
419 * @param widget the widget
420 * @return <code>true</code> if the widget displays the entire contents, i.e. it cannot
421 * be vertically scrolled, <code>false</code> otherwise
422 */
423 public static bool isShowingEntireContents(StyledText widget) {
424 if (widget.getTopPixel() !is 0) // more efficient shortcut
425 return false;
426
427 int lastVisiblePixel= computeLastVisiblePixel(widget);
428 int lastPossiblePixel= widget.getLinePixel(widget.getLineCount());
429 return lastPossiblePixel <= lastVisiblePixel;
430 }
431
432 /**
433 * Determines the graphical area covered by the given text region in
434 * the given viewer.
435 *
436 * @param region the region whose graphical extend must be computed
437 * @param textViewer the text viewer containing the region
438 * @return the graphical extend of the given region in the given viewer
439 *
440 * @since 3.4
441 */
442 public static Rectangle computeArea(IRegion region, ITextViewer textViewer) {
443 int start= 0;
444 int end= 0;
445 IRegion widgetRegion= modelRange2WidgetRange(region, textViewer);
446 if (widgetRegion !is null) {
447 start= widgetRegion.getOffset();
448 end= start + widgetRegion.getLength();
449 }
450
451 StyledText styledText= textViewer.getTextWidget();
452 Rectangle bounds;
453 if (end > 0 && start < end)
454 bounds= styledText.getTextBounds(start, end - 1);
455 else {
456 Point loc= styledText.getLocationAtOffset(start);
457 bounds= new Rectangle(loc.x, loc.y, getAverageCharWidth(textViewer.getTextWidget()), styledText.getLineHeight(start));
458 }
459
460 return new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
461 }
462
463 /**
464 * Translates a given region of the text viewer's document into
465 * the corresponding region of the viewer's widget.
466 *
467 * @param region the document region
468 * @param textViewer the viewer containing the region
469 * @return the corresponding widget region
470 *
471 * @since 3.4
472 */
473 private static IRegion modelRange2WidgetRange(IRegion region, ITextViewer textViewer) {
474 if ( cast(ITextViewerExtension5)textViewer ) {
475 ITextViewerExtension5 extension= cast(ITextViewerExtension5) textViewer;
476 return extension.modelRange2WidgetRange(region);
477 }
478
479 IRegion visibleRegion= textViewer.getVisibleRegion();
480 int start= region.getOffset() - visibleRegion.getOffset();
481 int end= start + region.getLength();
482 if (end > visibleRegion.getLength())
483 end= visibleRegion.getLength();
484
485 return new Region(start, end - start);
486 }
487
488 /**
489 * Returns the average character width of the given control's font.
490 *
491 * @param control the control to calculate the average char width for
492 * @return the average character width of the controls font
493 *
494 * @since 3.4
495 */
496 public static int getAverageCharWidth(Control control) {
497 GC gc= new GC(control);
498 gc.setFont(control.getFont());
499 int increment= gc.getFontMetrics().getAverageCharWidth();
500 gc.dispose();
501 return increment;
502 }
503
504 }