Mercurial > projects > dwt2
diff org.eclipse.jface.text/src/org/eclipse/jface/text/TextPresentation.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 | 52184e4b815c |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/TextPresentation.d Sat Mar 14 18:23:29 2009 +0100 @@ -0,0 +1,875 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit <benoit@tionex.de> + *******************************************************************************/ +module org.eclipse.jface.text.TextPresentation; + +import org.eclipse.jface.text.IDocumentPartitioningListener; // packageimport +import org.eclipse.jface.text.DefaultTextHover; // packageimport +import org.eclipse.jface.text.AbstractInformationControl; // packageimport +import org.eclipse.jface.text.TextUtilities; // packageimport +import org.eclipse.jface.text.IInformationControlCreatorExtension; // packageimport +import org.eclipse.jface.text.AbstractInformationControlManager; // packageimport +import org.eclipse.jface.text.ITextViewerExtension2; // packageimport +import org.eclipse.jface.text.IDocumentPartitioner; // packageimport +import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy; // packageimport +import org.eclipse.jface.text.ITextSelection; // packageimport +import org.eclipse.jface.text.Document; // packageimport +import org.eclipse.jface.text.FindReplaceDocumentAdapterContentProposalProvider; // packageimport +import org.eclipse.jface.text.ITextListener; // packageimport +import org.eclipse.jface.text.BadPartitioningException; // packageimport +import org.eclipse.jface.text.ITextViewerExtension5; // packageimport +import org.eclipse.jface.text.IDocumentPartitionerExtension3; // packageimport +import org.eclipse.jface.text.IUndoManager; // packageimport +import org.eclipse.jface.text.ITextHoverExtension2; // packageimport +import org.eclipse.jface.text.IRepairableDocument; // packageimport +import org.eclipse.jface.text.IRewriteTarget; // packageimport +import org.eclipse.jface.text.DefaultPositionUpdater; // packageimport +import org.eclipse.jface.text.RewriteSessionEditProcessor; // packageimport +import org.eclipse.jface.text.TextViewerHoverManager; // packageimport +import org.eclipse.jface.text.DocumentRewriteSession; // packageimport +import org.eclipse.jface.text.TextViewer; // packageimport +import org.eclipse.jface.text.ITextViewerExtension8; // packageimport +import org.eclipse.jface.text.RegExMessages; // packageimport +import org.eclipse.jface.text.IDelayedInputChangeProvider; // packageimport +import org.eclipse.jface.text.ITextOperationTargetExtension; // packageimport +import org.eclipse.jface.text.IWidgetTokenOwner; // packageimport +import org.eclipse.jface.text.IViewportListener; // packageimport +import org.eclipse.jface.text.GapTextStore; // packageimport +import org.eclipse.jface.text.MarkSelection; // packageimport +import org.eclipse.jface.text.IDocumentPartitioningListenerExtension; // packageimport +import org.eclipse.jface.text.IDocumentAdapterExtension; // packageimport +import org.eclipse.jface.text.IInformationControlExtension; // packageimport +import org.eclipse.jface.text.IDocumentPartitioningListenerExtension2; // packageimport +import org.eclipse.jface.text.DefaultDocumentAdapter; // packageimport +import org.eclipse.jface.text.ITextViewerExtension3; // packageimport +import org.eclipse.jface.text.IInformationControlCreator; // packageimport +import org.eclipse.jface.text.TypedRegion; // packageimport +import org.eclipse.jface.text.ISynchronizable; // packageimport +import org.eclipse.jface.text.IMarkRegionTarget; // packageimport +import org.eclipse.jface.text.TextViewerUndoManager; // packageimport +import org.eclipse.jface.text.IRegion; // packageimport +import org.eclipse.jface.text.IInformationControlExtension2; // packageimport +import org.eclipse.jface.text.IDocumentExtension4; // packageimport +import org.eclipse.jface.text.IDocumentExtension2; // packageimport +import org.eclipse.jface.text.IDocumentPartitionerExtension2; // packageimport +import org.eclipse.jface.text.DefaultInformationControl; // packageimport +import org.eclipse.jface.text.IWidgetTokenOwnerExtension; // packageimport +import org.eclipse.jface.text.DocumentClone; // packageimport +import org.eclipse.jface.text.DefaultUndoManager; // packageimport +import org.eclipse.jface.text.IFindReplaceTarget; // packageimport +import org.eclipse.jface.text.IAutoEditStrategy; // packageimport +import org.eclipse.jface.text.ILineTrackerExtension; // packageimport +import org.eclipse.jface.text.IUndoManagerExtension; // packageimport +import org.eclipse.jface.text.TextSelection; // packageimport +import org.eclipse.jface.text.DefaultAutoIndentStrategy; // packageimport +import org.eclipse.jface.text.IAutoIndentStrategy; // packageimport +import org.eclipse.jface.text.IPainter; // packageimport +import org.eclipse.jface.text.IInformationControl; // packageimport +import org.eclipse.jface.text.IInformationControlExtension3; // packageimport +import org.eclipse.jface.text.ITextViewerExtension6; // packageimport +import org.eclipse.jface.text.IInformationControlExtension4; // packageimport +import org.eclipse.jface.text.DefaultLineTracker; // packageimport +import org.eclipse.jface.text.IDocumentInformationMappingExtension; // packageimport +import org.eclipse.jface.text.IRepairableDocumentExtension; // packageimport +import org.eclipse.jface.text.ITextHover; // packageimport +import org.eclipse.jface.text.FindReplaceDocumentAdapter; // packageimport +import org.eclipse.jface.text.ILineTracker; // packageimport +import org.eclipse.jface.text.Line; // packageimport +import org.eclipse.jface.text.ITextViewerExtension; // packageimport +import org.eclipse.jface.text.IDocumentAdapter; // packageimport +import org.eclipse.jface.text.TextEvent; // packageimport +import org.eclipse.jface.text.BadLocationException; // packageimport +import org.eclipse.jface.text.AbstractDocument; // packageimport +import org.eclipse.jface.text.AbstractLineTracker; // packageimport +import org.eclipse.jface.text.TreeLineTracker; // packageimport +import org.eclipse.jface.text.ITextPresentationListener; // packageimport +import org.eclipse.jface.text.Region; // packageimport +import org.eclipse.jface.text.ITextViewer; // packageimport +import org.eclipse.jface.text.IDocumentInformationMapping; // packageimport +import org.eclipse.jface.text.MarginPainter; // packageimport +import org.eclipse.jface.text.IPaintPositionManager; // packageimport +import org.eclipse.jface.text.IFindReplaceTargetExtension; // packageimport +import org.eclipse.jface.text.ISlaveDocumentManagerExtension; // packageimport +import org.eclipse.jface.text.ISelectionValidator; // packageimport +import org.eclipse.jface.text.IDocumentExtension; // packageimport +import org.eclipse.jface.text.PropagatingFontFieldEditor; // packageimport +import org.eclipse.jface.text.ConfigurableLineTracker; // packageimport +import org.eclipse.jface.text.SlaveDocumentEvent; // packageimport +import org.eclipse.jface.text.IDocumentListener; // packageimport +import org.eclipse.jface.text.PaintManager; // packageimport +import org.eclipse.jface.text.IFindReplaceTargetExtension3; // packageimport +import org.eclipse.jface.text.ITextDoubleClickStrategy; // packageimport +import org.eclipse.jface.text.IDocumentExtension3; // packageimport +import org.eclipse.jface.text.Position; // packageimport +import org.eclipse.jface.text.TextMessages; // packageimport +import org.eclipse.jface.text.CopyOnWriteTextStore; // packageimport +import org.eclipse.jface.text.WhitespaceCharacterPainter; // packageimport +import org.eclipse.jface.text.IPositionUpdater; // packageimport +import org.eclipse.jface.text.DefaultTextDoubleClickStrategy; // packageimport +import org.eclipse.jface.text.ListLineTracker; // packageimport +import org.eclipse.jface.text.ITextInputListener; // packageimport +import org.eclipse.jface.text.BadPositionCategoryException; // packageimport +import org.eclipse.jface.text.IWidgetTokenKeeperExtension; // packageimport +import org.eclipse.jface.text.IInputChangedListener; // packageimport +import org.eclipse.jface.text.ITextOperationTarget; // packageimport +import org.eclipse.jface.text.IDocumentInformationMappingExtension2; // packageimport +import org.eclipse.jface.text.ITextViewerExtension7; // packageimport +import org.eclipse.jface.text.IInformationControlExtension5; // packageimport +import org.eclipse.jface.text.IDocumentRewriteSessionListener; // packageimport +import org.eclipse.jface.text.JFaceTextUtil; // packageimport +import org.eclipse.jface.text.AbstractReusableInformationControlCreator; // packageimport +import org.eclipse.jface.text.TabsToSpacesConverter; // packageimport +import org.eclipse.jface.text.CursorLinePainter; // packageimport +import org.eclipse.jface.text.ITextHoverExtension; // packageimport +import org.eclipse.jface.text.IEventConsumer; // packageimport +import org.eclipse.jface.text.IDocument; // packageimport +import org.eclipse.jface.text.IWidgetTokenKeeper; // packageimport +import org.eclipse.jface.text.DocumentCommand; // packageimport +import org.eclipse.jface.text.TypedPosition; // packageimport +import org.eclipse.jface.text.IEditingSupportRegistry; // packageimport +import org.eclipse.jface.text.IDocumentPartitionerExtension; // packageimport +import org.eclipse.jface.text.AbstractHoverInformationControlManager; // packageimport +import org.eclipse.jface.text.IEditingSupport; // packageimport +import org.eclipse.jface.text.IMarkSelection; // packageimport +import org.eclipse.jface.text.ISlaveDocumentManager; // packageimport +import org.eclipse.jface.text.DocumentEvent; // packageimport +import org.eclipse.jface.text.DocumentPartitioningChangedEvent; // packageimport +import org.eclipse.jface.text.ITextStore; // packageimport +import org.eclipse.jface.text.JFaceTextMessages; // packageimport +import org.eclipse.jface.text.DocumentRewriteSessionEvent; // packageimport +import org.eclipse.jface.text.SequentialRewriteTextStore; // packageimport +import org.eclipse.jface.text.DocumentRewriteSessionType; // packageimport +import org.eclipse.jface.text.TextAttribute; // packageimport +import org.eclipse.jface.text.ITextViewerExtension4; // packageimport +import org.eclipse.jface.text.ITypedRegion; // packageimport + +import java.lang.all; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Set; +import tango.core.Exception; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyleRange; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.core.runtime.Assert; + + +/** + * Describes the presentation styles for a section of an indexed text such as a + * document or string. A text presentation defines a default style for the whole + * section and in addition style differences for individual subsections. Text + * presentations can be narrowed down to a particular result window. All methods + * are result window aware, i.e. ranges outside the result window are always + * ignored. + * <p> + * All iterators provided by a text presentation assume that they enumerate non + * overlapping, consecutive ranges inside the default range. Thus, all these + * iterators do not include the default range. The default style range must be + * explicitly asked for using <code>getDefaultStyleRange</code>. + */ +public class TextPresentation { + + /** + * Applies the given presentation to the given text widget. Helper method. + * + * @param presentation the style information + * @param text the widget to which to apply the style information + * @since 2.0 + */ + public static void applyTextPresentation(TextPresentation presentation, StyledText text) { + + StyleRange[] ranges= new StyleRange[presentation.getDenumerableRanges()]; + + int i= 0; + Iterator e= presentation.getAllStyleRangeIterator(); + while (e.hasNext()) + ranges[i++]= cast(StyleRange) e.next(); + + text.setStyleRanges(ranges); + } + + + + + /** + * Enumerates all the <code>StyleRange</code>s included in the presentation. + */ + class FilterIterator : Iterator { + + /** The index of the next style range to be enumerated */ + protected int fIndex; + /** The upper bound of the indices of style ranges to be enumerated */ + protected int fLength; + /** Indicates whether ranges similar to the default range should be enumerated */ + protected bool fSkipDefaults; + /** The result window */ + protected IRegion fWindow; + + /** + * <code>skipDefaults</code> tells the enumeration to skip all those style ranges + * which define the same style as the presentation's default style range. + * + * @param skipDefaults <code>false</code> if ranges similar to the default range should be enumerated + */ + protected this(bool skipDefaults) { + + fSkipDefaults= skipDefaults; + + fWindow= fResultWindow; + fIndex= getFirstIndexInWindow(fWindow); + fLength= getFirstIndexAfterWindow(fWindow); + + if (fSkipDefaults) + computeIndex(); + } + + /* + * @see Iterator#next() + */ + public Object next() { + try { + StyleRange r= cast(StyleRange) fRanges.get(fIndex++); + return createWindowRelativeRange(fWindow, r); + } catch (ArrayIndexOutOfBoundsException x) { + throw new NoSuchElementException(null); + } finally { + if (fSkipDefaults) + computeIndex(); + } + } + + /* + * @see Iterator#hasNext() + */ + public bool hasNext() { + return fIndex < fLength; + } + + /* + * @see Iterator#remove() + */ + public void remove() { + throw new UnsupportedOperationException(); + } + + /** + * Returns whether the given object should be skipped. + * + * @param o the object to be checked + * @return <code>true</code> if the object should be skipped by the iterator + */ + protected bool skip(Object o) { + StyleRange r= cast(StyleRange) o; + return r.similarTo(fDefaultRange); + } + + /** + * Computes the index of the styled range that is the next to be enumerated. + */ + protected void computeIndex() { + while (fIndex < fLength && skip(fRanges.get(fIndex))) + ++ fIndex; + } + } + + /** The style information for the range covered by the whole presentation */ + private StyleRange fDefaultRange; + /** The member ranges of the presentation */ + private ArrayList fRanges; + /** A clipping region against which the presentation can be clipped when asked for results */ + private IRegion fResultWindow; + /** + * The optional extent for this presentation. + * @since 3.0 + */ + private IRegion fExtent; + + + /** + * Creates a new empty text presentation. + */ + public this() { + fRanges= new ArrayList(50); + } + + /** + * Creates a new empty text presentation. <code>sizeHint</code> tells the + * expected size of this presentation. + * + * @param sizeHint the expected size of this presentation + */ + public this(int sizeHint) { + Assert.isTrue(sizeHint > 0); + fRanges= new ArrayList(sizeHint); + } + + /** + * Creates a new empty text presentation with the given extent. + * <code>sizeHint</code> tells the expected size of this presentation. + * + * @param extent the extent of the created <code>TextPresentation</code> + * @param sizeHint the expected size of this presentation + * @since 3.0 + */ + public this(IRegion extent, int sizeHint) { + this(sizeHint); + Assert.isNotNull(cast(Object)extent); + fExtent= extent; + } + + /** + * Sets the result window for this presentation. When dealing with + * this presentation all ranges which are outside the result window + * are ignored. For example, the size of the presentation is 0 + * when there is no range inside the window even if there are ranges + * outside the window. All methods are aware of the result window. + * + * @param resultWindow the result window + */ + public void setResultWindow(IRegion resultWindow) { + fResultWindow= resultWindow; + } + + /** + * Set the default style range of this presentation. + * The default style range defines the overall area covered + * by this presentation and its style information. + * + * @param range the range describing the default region + */ + public void setDefaultStyleRange(StyleRange range) { + fDefaultRange= range; + } + + /** + * Returns this presentation's default style range. The returned <code>StyleRange</code> + * is relative to the start of the result window. + * + * @return this presentation's default style range + */ + public StyleRange getDefaultStyleRange() { + StyleRange range= createWindowRelativeRange(fResultWindow, fDefaultRange); + if (range is null) + return null; + return cast(StyleRange)range.clone(); + + } + + /** + * Add the given range to the presentation. The range must be a + * subrange of the presentation's default range. + * + * @param range the range to be added + */ + public void addStyleRange(StyleRange range) { + checkConsistency(range); + fRanges.add(range); + } + + /** + * Replaces the given range in this presentation. The range must be a + * subrange of the presentation's default range. + * + * @param range the range to be added + * @since 3.0 + */ + public void replaceStyleRange(StyleRange range) { + applyStyleRange(range, false); + } + + /** + * Merges the given range into this presentation. The range must be a + * subrange of the presentation's default range. + * + * @param range the range to be added + * @since 3.0 + */ + public void mergeStyleRange(StyleRange range) { + applyStyleRange(range, true); + } + + /** + * Applies the given range to this presentation. The range must be a + * subrange of the presentation's default range. + * + * @param range the range to be added + * @param merge <code>true</code> if the style should be merged instead of replaced + * @since 3.0 + */ + private void applyStyleRange(StyleRange range, bool merge) { + if (range.length is 0) + return; + + checkConsistency(range); + + int start= range.start; + int length= range.length; + int end= start + length; + + if (fRanges.size() is 0) { + StyleRange defaultRange= getDefaultStyleRange(); + if (defaultRange is null) + defaultRange= range; + + defaultRange.start= start; + defaultRange.length= length; + applyStyle(range, defaultRange, merge); + fRanges.add(defaultRange); + } else { + IRegion rangeRegion= new Region(start, length); + int first= getFirstIndexInWindow(rangeRegion); + + if (first is fRanges.size()) { + StyleRange defaultRange= getDefaultStyleRange(); + if (defaultRange is null) + defaultRange= range; + defaultRange.start= start; + defaultRange.length= length; + applyStyle(range, defaultRange, merge); + fRanges.add(defaultRange); + return; + } + + int last= getFirstIndexAfterWindow(rangeRegion); + for (int i= first; i < last && length > 0; i++) { + + StyleRange current= cast(StyleRange)fRanges.get(i); + int currentStart= current.start; + int currentEnd= currentStart + current.length; + + if (end <= currentStart) { + fRanges.add(i, range); + return; + } + + if (start >= currentEnd) + continue; + + StyleRange currentCopy= null; + if (end < currentEnd) + currentCopy= cast(StyleRange)current.clone(); + + if (start < currentStart) { + // Apply style to new default range and add it + StyleRange defaultRange= getDefaultStyleRange(); + if (defaultRange is null) + defaultRange= new StyleRange(); + + defaultRange.start= start; + defaultRange.length= currentStart - start; + applyStyle(range, defaultRange, merge); + fRanges.add(i, defaultRange); + i++; last++; + + + // Apply style to first part of current range + current.length= Math.min(end, currentEnd) - currentStart; + applyStyle(range, current, merge); + } + + if (start >= currentStart) { + // Shorten the current range + current.length= start - currentStart; + + // Apply the style to the rest of the current range and add it + if (current.length > 0) { + current= cast(StyleRange)current.clone(); + i++; last++; + fRanges.add(i, current); + } + applyStyle(range, current, merge); + current.start= start; + current.length= Math.min(end, currentEnd) - start; + } + + if (end < currentEnd) { + // Add rest of current range + currentCopy.start= end; + currentCopy.length= currentEnd - end; + i++; last++; + fRanges.add(i, currentCopy); + } + + // Update range + range.start= currentEnd; + range.length= Math.max(end - currentEnd, 0); + start= range.start; + length= range.length; + } + if (length > 0) { + // Apply style to new default range and add it + StyleRange defaultRange= getDefaultStyleRange(); + if (defaultRange is null) + defaultRange= range; + defaultRange.start= start; + defaultRange.length= end - start; + applyStyle(range, defaultRange, merge); + fRanges.add(last, defaultRange); + } + } + } + + /** + * Replaces the given ranges in this presentation. Each range must be a + * subrange of the presentation's default range. The ranges must be ordered + * by increasing offset and must not overlap (but may be adjacent). + * + * @param ranges the ranges to be added + * @since 3.0 + */ + public void replaceStyleRanges(StyleRange[] ranges) { + applyStyleRanges(ranges, false); + } + + /** + * Merges the given ranges into this presentation. Each range must be a + * subrange of the presentation's default range. The ranges must be ordered + * by increasing offset and must not overlap (but may be adjacent). + * + * @param ranges the ranges to be added + * @since 3.0 + */ + public void mergeStyleRanges(StyleRange[] ranges) { + applyStyleRanges(ranges, true); + } + + /** + * Applies the given ranges to this presentation. Each range must be a + * subrange of the presentation's default range. The ranges must be ordered + * by increasing offset and must not overlap (but may be adjacent). + * + * @param ranges the ranges to be added + * @param merge <code>true</code> if the style should be merged instead of replaced + * @since 3.0 + */ + private void applyStyleRanges(StyleRange[] ranges, bool merge) { + int j= 0; + ArrayList oldRanges= fRanges; + ArrayList newRanges= new ArrayList(2*ranges.length + oldRanges.size()); + for (int i= 0, n= ranges.length; i < n; i++) { + StyleRange range= ranges[i]; + fRanges= oldRanges; // for getFirstIndexAfterWindow(...) + for (int m= getFirstIndexAfterWindow(new Region(range.start, range.length)); j < m; j++) + newRanges.add(oldRanges.get(j)); + fRanges= newRanges; // for mergeStyleRange(...) + applyStyleRange(range, merge); + } + for (int m= oldRanges.size(); j < m; j++) + newRanges.add(oldRanges.get(j)); + fRanges= newRanges; + } + + /** + * Applies the template_'s style to the target. + * + * @param template_ the style range to be used as template_ + * @param target the style range to which to apply the template_ + * @param merge <code>true</code> if the style should be merged instead of replaced + * @since 3.0 + */ + private void applyStyle(StyleRange template_, StyleRange target, bool merge) { + if (merge) { + if (template_.font !is null) + target.font= template_.font; + target.fontStyle|= template_.fontStyle; + + if (template_.metrics !is null) + target.metrics= template_.metrics; + + if (template_.foreground !is null) + target.foreground= template_.foreground; + if (template_.background !is null) + target.background= template_.background; + + target.strikeout|= template_.strikeout; + if (template_.strikeoutColor !is null) + target.strikeoutColor= template_.strikeoutColor; + + target.underline|= template_.underline; + if (template_.underlineStyle !is SWT.NONE) + target.underlineStyle= template_.underlineStyle; + if (template_.underlineColor !is null) + target.underlineColor= template_.underlineColor; + + if (template_.borderStyle !is SWT.NONE) + target.borderStyle= template_.borderStyle; + if (template_.borderColor !is null) + target.borderColor= template_.borderColor; + + } else { + target.font= template_.font; + target.fontStyle= template_.fontStyle; + target.metrics= template_.metrics; + target.foreground= template_.foreground; + target.background= template_.background; + target.strikeout= template_.strikeout; + target.strikeoutColor= template_.strikeoutColor; + target.underline= template_.underline; + target.underlineStyle= template_.underlineStyle; + target.underlineColor= template_.underlineColor; + target.borderStyle= template_.borderStyle; + target.borderColor= template_.borderColor; + } + } + + /** + * Checks whether the given range is a subrange of the presentation's + * default style range. + * + * @param range the range to be checked + * @exception IllegalArgumentException if range is not a subrange of the presentation's default range + */ + private void checkConsistency(StyleRange range) { + + if (range is null) + throw new IllegalArgumentException(null); + + if (fDefaultRange !is null) { + + if (range.start < fDefaultRange.start) + range.start= fDefaultRange.start; + + int defaultEnd= fDefaultRange.start + fDefaultRange.length; + int end= range.start + range.length; + if (end > defaultEnd) + range.length -= (end - defaultEnd); + } + } + + /** + * Returns the index of the first range which overlaps with the + * specified window. + * + * @param window the window to be used for searching + * @return the index of the first range overlapping with the window + */ + private int getFirstIndexInWindow(IRegion window) { + if (window !is null) { + int start= window.getOffset(); + int i= -1, j= fRanges.size(); + while (j - i > 1) { + int k= (i + j) >> 1; + StyleRange r= cast(StyleRange) fRanges.get(k); + if (r.start + r.length > start) + j= k; + else + i= k; + } + return j; + } + return 0; + } + + /** + * Returns the index of the first range which comes after the specified window and does + * not overlap with this window. + * + * @param window the window to be used for searching + * @return the index of the first range behind the window and not overlapping with the window + */ + private int getFirstIndexAfterWindow(IRegion window) { + if (window !is null) { + int end= window.getOffset() + window.getLength(); + int i= -1, j= fRanges.size(); + while (j - i > 1) { + int k= (i + j) >> 1; + StyleRange r= cast(StyleRange) fRanges.get(k); + if (r.start < end) + i= k; + else + j= k; + } + return j; + } + return fRanges.size(); + } + + /** + * Returns a style range which is relative to the specified window and + * appropriately clipped if necessary. The original style range is not + * modified. + * + * @param window the reference window + * @param range the absolute range + * @return the window relative range based on the absolute range + */ + private StyleRange createWindowRelativeRange(IRegion window, StyleRange range) { + if (window is null || range is null) + return range; + + int start= range.start - window.getOffset(); + if (start < 0) + start= 0; + + int rangeEnd= range.start + range.length; + int windowEnd= window.getOffset() + window.getLength(); + int end= (rangeEnd > windowEnd ? windowEnd : rangeEnd); + end -= window.getOffset(); + + StyleRange newRange= cast(StyleRange) range.clone(); + newRange.start= start; + newRange.length= end - start; + return newRange; + } + + /** + * Returns the region which is relative to the specified window and + * appropriately clipped if necessary. + * + * @param coverage the absolute coverage + * @return the window relative region based on the absolute coverage + * @since 3.0 + */ + private IRegion createWindowRelativeRegion(IRegion coverage) { + if (fResultWindow is null || coverage is null) + return coverage; + + int start= coverage.getOffset() - fResultWindow.getOffset(); + if (start < 0) + start= 0; + + int rangeEnd= coverage.getOffset() + coverage.getLength(); + int windowEnd= fResultWindow.getOffset() + fResultWindow.getLength(); + int end= (rangeEnd > windowEnd ? windowEnd : rangeEnd); + end -= fResultWindow.getOffset(); + + return new Region(start, end - start); + } + + /** + * Returns an iterator which enumerates all style ranged which define a style + * different from the presentation's default style range. The default style range + * is not enumerated. + * + * @return a style range iterator + */ + public Iterator getNonDefaultStyleRangeIterator() { + return new FilterIterator(fDefaultRange !is null); + } + + /** + * Returns an iterator which enumerates all style ranges of this presentation + * except the default style range. The returned <code>StyleRange</code>s + * are relative to the start of the presentation's result window. + * + * @return a style range iterator + */ + public Iterator getAllStyleRangeIterator() { + return new FilterIterator(false); + } + + /** + * Returns whether this collection contains any style range including + * the default style range. + * + * @return <code>true</code> if there is no style range in this presentation + */ + public bool isEmpty() { + return (fDefaultRange is null && getDenumerableRanges() is 0); + } + + /** + * Returns the number of style ranges in the presentation not counting the default + * style range. + * + * @return the number of style ranges in the presentation excluding the default style range + */ + public int getDenumerableRanges() { + int size= getFirstIndexAfterWindow(fResultWindow) - getFirstIndexInWindow(fResultWindow); + return (size < 0 ? 0 : size); + } + + /** + * Returns the style range with the smallest offset ignoring the default style range or null + * if the presentation is empty. + * + * @return the style range with the smallest offset different from the default style range + */ + public StyleRange getFirstStyleRange() { + try { + + StyleRange range= cast(StyleRange) fRanges.get(getFirstIndexInWindow(fResultWindow)); + return createWindowRelativeRange(fResultWindow, range); + + } catch (NoSuchElementException x) { + } catch (IndexOutOfBoundsException x) { + } + + return null; + } + + /** + * Returns the style range with the highest offset ignoring the default style range. + * + * @return the style range with the highest offset different from the default style range + */ + public StyleRange getLastStyleRange() { + try { + + StyleRange range= cast(StyleRange) fRanges.get(getFirstIndexAfterWindow(fResultWindow) - 1); + return createWindowRelativeRange(fResultWindow, range); + + } catch (NoSuchElementException x) { + return null; + } catch (IndexOutOfBoundsException x) { + return null; + } + } + + /** + * Returns the coverage of this presentation as clipped by the presentation's + * result window. + * + * @return the coverage of this presentation + */ + public IRegion getCoverage() { + + if (fDefaultRange !is null) { + StyleRange range= getDefaultStyleRange(); + return new Region(range.start, range.length); + } + + StyleRange first= getFirstStyleRange(); + StyleRange last= getLastStyleRange(); + + if (first is null || last is null) + return null; + + return new Region(first.start, last.start - first. start + last.length); + } + + /** + * Returns the extent of this presentation clipped by the + * presentation's result window. + * + * @return the clipped extent + * @since 3.0 + */ + public IRegion getExtent() { + if (fExtent !is null) + return createWindowRelativeRegion(fExtent); + return getCoverage(); + } + + /** + * Clears this presentation by resetting all applied changes. + * @since 2.0 + */ + public void clear() { + fDefaultRange= null; + fResultWindow= null; + fRanges.clear(); + } + + +}