Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 175676 Details for
Bug 119384
[api] Add new API to support memory efficient StyleRange support in StyledText
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
Extended version of TextPresentation (Updated)
TdTextPresentation.java (text/x-java-source), 37.00 KB, created by
Bill Fenlason
on 2010-08-01 20:12:10 EDT
(
hide
)
Description:
Extended version of TextPresentation (Updated)
Filename:
MIME Type:
Creator:
Bill Fenlason
Created:
2010-08-01 20:12:10 EDT
Size:
37.00 KB
patch
obsolete
>/******************************************************************************* > * Copyright (c) 2000, 2008 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 > *******************************************************************************/ > >/// All new or modified source code herein is made available under the terms >/// of the Eclipse Public License v1.0 by William Fenlason, August 1, 2010 > > >/// This is a modified version of TextPresentation >/// >/// Design notes (see bug 119384) >/// >/// All descriptive information is in line comments beginning with /// >/// which may be removed as desired. >/// >/// This is a revised version of the TextPresentation to take advantage of the >/// new (Eclipse 3.3) styled text widget interface. It is intended to be >/// fully compatible with the current TextPresentation implementation, and >/// no existing API is intentionally broken. >/// >/// The StyleRange object is problematic when it comes to performance and >/// storage usage. Each range object includes an offset, length and >/// style, and there are typically several ranges for each line in a file. >/// For very large files this can be a performance problem. The performance >/// improvement is caused by preventing the creation of a StyleRange object >/// (or other unnecessary objects) for each field or token. >/// >/// When this was recognized, the StyledText widget provided an >/// interface in which separate arrays of offset/length pairs and model >/// style ranges are passed to the widget for updating. >/// >/// This implementation allows for the use of that interface rather than >/// creating separate style range objects for each field in the file. >/// >/// SUMMARY of NEW API >/// >/// Four new public methods are added. The first three are additional >/// versions of addStyleRange, replaceStyleRange and MergeStyleRange. >/// >/// In each case, the argument list consists of the StyleRange, the >/// explicit starting offset, and the explicit length. The StyleRange >/// specified must be a model style range, with a zero offset and length, >/// and the offset and length arguments are integers (int). >/// >/// This API allows model style ranges to be added to the presentation >/// without forcing the construction of a distinct StyleRange object with >/// a nonzero length. >/// >/// The fourth API addition retrieves a new iterator for the StyleRange >/// objects. The purpose of this iterator is to allow the return of the >/// StyleRange objects which may be models and the associated offset and >/// length without forcing the construction of a StyleRange object. >/// >/// The iterator provides the normal hasNext() and next() methods, >/// but also provides two additional methods: getOffset() and getLength() >/// which return the integer offset and length of the last retrieved >/// StyleRange object. >/// >/// SUMMARY of DESIGN CHANGES >/// >/// A straight forward approach is used. The prior version accumulates the >/// StyleRange objects in an ArrayList, and that continues to be the case. >/// >/// A new integer array of offset-length pairs is added. The offset and >/// length of each StyleRange that is added (either with the initial API or >/// the new API) is stored in the integer array. >/// >/// By keeping the offset and length information separately, the ArrayList >/// of style ranges can now contain duplicate references to model style >/// ranges. >/// >/// In order to allow the previous iterators to work, each StyleRange is >/// checked to see if it is a model before it is returned. If so, a new >/// StyleRange object with the correct offset and length (taken from the >/// integer array) is returned. Thus if the new API is used to add model >/// style ranges and the old API is used to retrieve them, new StyleRange >/// objects will be created (but that can not be avoided). If the new API >/// is used to store and retrieve the StyleRanges, only model style ranges >/// need be used. >/// >/// The static public convenience method applyTextPresentation which may be >/// used to apply a presentation to a StyledText widget is modified to use >/// the new API. The method is no longer used by the TextViewer because the >/// TextViewer must translate the style range in case folding is in effect, >/// but the rewritten version demonstrates the use of the new API. >/// >/// A number of the private methods were modified for this change, and some >/// new private methods were added. Many of these changes are straight >/// forward and use the explicit offset-length array rather than the values >/// contained in the StyleRange object. The following are noted. >/// >/// The argument list of the checkConsistency method was modified to add the >/// explicit offset and length. More importantly, the documentation for the >/// method did not match the implementation in that the documentation >/// indicated that an exception would be thrown if the range was not a subset >/// of the default range (if specified). Instead, the code truncated the >/// specified range to fit the default range. The code was changed so that >/// it matches the documentation and throws the exception. >/// >/// The applyStyleRange method was totally rewritten and uses a modified >/// version of the original code. >/// >/// SUMMARY of API CHANGES >/// >/// Two minor changes to the existing API behavior should be noted. The >/// original public addStyleRange method simply added the supplied StyleRange >/// to the ArrayList without performing any checking. As bug 138861 pointed >/// out, that allowed the array list to contain ranges that were out of order >/// or overlapping. Clearly either the supplied range should be checked to >/// determine if it is out of order or overlapping, or it should be accepted >/// and processed as a replacement. The latter was implemented. One >/// result of this choice is that there is no difference between adding a >/// StyleRange and replacing one. >/// >/// When StyleRanges are added or replaced, the result window (if set) is no >/// longer examined, but the range is added or replaced as specified. The >/// reason is to avoid problems in which the specified range is only partially >/// within the window. >/// >/// When StyleRanges are retrieved, the result window (if set) is honored as >/// intended. > >package viewer; > >import org.eclipse.jface.text.IRegion; >import org.eclipse.jface.text.Region; >import org.eclipse.jface.text.TextPresentation; > >import java.util.ArrayList; >import java.util.Iterator; >import java.util.NoSuchElementException; > >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 TdTextPresentation extends 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(TdTextPresentation presentation, StyledText text) { > int size = presentation.getDenumerableRanges(); > if (size == 0) return; > > StyleRange[] ranges = new StyleRange[size]; > int[] offsetLengthPairs = new int[size *2]; > > StyleRangeIterator e = presentation.getStyleRangeModelIterator(); > > for (int index = 0; e.hasNext(); index += 1) { > ranges[index] = (StyleRange) e.next(); > offsetLengthPairs[index *2] = e.getOffset(); > offsetLengthPairs[1 + index *2] = e.getLength(); > } > > int start = offsetLengthPairs[0]; > int length = offsetLengthPairs[(size*2) -2] + offsetLengthPairs[(size *2) -1]; > > text.setStyleRanges(start, length, offsetLengthPairs, ranges); > } > > > > > /** > * Enumerates all the <code>StyleRange</code>s included in the presentation. > */ > class FilterIterator implements 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 boolean 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 FilterIterator(boolean skipDefaults) { > > fSkipDefaults= skipDefaults; > > fWindow= fResultWindow; > fIndex= getFirstIndexInWindow(fWindow); > fLength= getFirstIndexAfterWindow(fWindow); > > if (fSkipDefaults) > computeIndex(); > } > > /* > * @see Iterator#next() > */ > public Object next() { > try { > StyleRange r= (StyleRange) fRanges.get(fIndex++); > return createWindowRelativeRange(fWindow, r, fOffsetLengths[fIndex *2 -2], fOffsetLengths[fIndex*2 -1]); > } catch (ArrayIndexOutOfBoundsException x) { > throw new NoSuchElementException(); > } finally { > if (fSkipDefaults) > computeIndex(); > } > } > > /* > * @see Iterator#hasNext() > */ > public boolean 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 boolean skip(Object o) { > StyleRange r= (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; > } > } > > /** > * Enumerates all the model <code>StyleRange</code>s included > * in the presentation as clipped by the result window. > */ > class StyleRangeIterator implements Iterator { > > /** The lower bound of the indices of style ranges to be enumerated */ > protected int fFirstIndex; > > /** The upper bound of the indices of style ranges to be enumerated */ > protected int fLastIndex; > > /** The index of the next text style to be enumerated */ > protected int fIndex; > > /** @see Iterator */ > protected StyleRangeIterator() { > fIndex = fFirstIndex = getFirstIndexInWindow(fResultWindow); > fLastIndex = getFirstIndexAfterWindow(fResultWindow); > } > > /** @see Iterator#next() */ > public Object next() { > try { > return fRanges.get(fIndex++); > } catch (ArrayIndexOutOfBoundsException x) { > throw new NoSuchElementException(); > } > } > > /** @see Iterator#hasNext() */ > public boolean hasNext() { > return fIndex < fLastIndex; > } > > /** @see Iterator#remove() */ > public void remove() { > throw new UnsupportedOperationException(); > } > > /** > * Returns the offset of the last retrieved StyleRange > * > * @return the offset of the last retrieved StyleRange > * > * @throws NoSuchElementException if no StyleRange was returned > */ > public int getOffset() { > if (fIndex == fFirstIndex) > throw new NoSuchElementException(); > > return fOffsetLengths[fIndex*2 -2]; > } > > /** > * Returns the length of the last retrieved StyleRange > * > * @return the length of the last retrieved StyleRange > * > * @throws NoSuchElementException if no StyleRange was returned > */ > public int getLength() { > if (fIndex == fFirstIndex) > throw new NoSuchElementException(); > > return fOffsetLengths[fIndex*2 -1]; > } > } > > /** The style information for the range covered by the whole presentation */ > private StyleRange fDefaultRange; > /** The member ranges of the presentation */ > private ArrayList fRanges; > /** The style range offset-length pairs */ > private int[] fOffsetLengths; > /** 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 TdTextPresentation() { > this(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 TdTextPresentation(int sizeHint) { > Assert.isTrue(sizeHint > 0); > fRanges= new ArrayList(sizeHint); > fOffsetLengths = new int[sizeHint *2]; > } > > /** > * 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 TdTextPresentation(IRegion extent, int sizeHint) { > this(sizeHint); > Assert.isNotNull(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 == null) > return null; > return (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) { > applyStyleRange(range, false); > } > > /** > * Adds a model range to the presentation. > * > * The model range must have a starting offset and length of zero. > * > * If part or all of the range currently exists in the presentation > * it is replaced. > * > * @param range the model style range to be added > * @param start the starting range offset > * @param length the range length > */ > public void addStyleRange(StyleRange range, int start, int length ) { > if (range.start != 0 || range.length != 0) > throw new IllegalArgumentException(); > > applyStyleRange(range, start, length, false); > } > > /** > * 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); > } > > /** > * Replaces a range in the presentation with a model range. > * > * The model range must have a starting offset and length of zero. > * > * If part or all of the range does not currently exist in the > * presentation it is added. > * > * @param range the model style range > * @param start the range start offset > * @param length the range length > */ > public void replaceStyleRange(StyleRange range, int start, int length) { > if (range.start != 0 || range.length != 0) > throw new IllegalArgumentException(); > > applyStyleRange(range, start, length, 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); > } > > /** > * Merges a model range into this presentation. > * > * The model range must have a starting offset and length of zero. > * > * If part or all of the range does not currently exist in the > * presentation it is added. > * > * @param range the model style range > * @param start the range start offset > * @param length the range length > */ > public void mergeStyleRange(StyleRange range, int start, int length) { > if (range.start != 0 || range.length != 0) > throw new IllegalArgumentException(); > > applyStyleRange(range, start, length, 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, boolean merge) { > if (range == null) > throw new IllegalArgumentException(); > > if (range.length == 0) > return; > > applyStyleRange(range, range.start, range.length, merge); > > } > > /** > * 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 rangeStart the range start > * @param rangeLength the range length > * @param merge <code>true</code> if the style should be merged instead of replaced > * > * @throws IllegalArgumentException if the model range is null > * or has a nonzero starting offset or length, or if the > * specified starting offset is less than zero, or if the > * specified length is not greater than zero. > */ > private void applyStyleRange(StyleRange range, int start, int length, boolean merge) { > StyleRange newRange = range; > int newStart = start; > int newLength = length; > int newEnd = start + length; > > StyleRange mergeRange = null; > > int deleteStart = 0; > int deleteLength = 0; > > int index = fRanges.size(); > > checkConsistency(newRange, newStart, newLength); > > // Search the list unless adding at the end > if (index > 0) { > int last = fOffsetLengths[index *2 -2] + fOffsetLengths[index *2 -1]; > if (newStart < last) > index = 0; > } > > for (;; index += 1) { > > // Handle insert at end > if (index == fRanges.size()) { > insertSpace(index); > setRange(index, newRange, newStart, newLength, merge, mergeRange); > break; > } > > int nextStart = fOffsetLengths[index *2]; > int nextEnd = nextStart + fOffsetLengths[index *2 +1]; > > // Continue if just searching > if (newStart >= nextEnd) > continue; > > // Split the current range if necessary > if (nextStart < newStart) { > StyleRange r = makeModel(index); > fOffsetLengths[index *2] = newStart; > fOffsetLengths[index *2 +1] = nextEnd - newStart; > > insertSpace(index); > setRange(index, r, nextStart, newStart - nextStart, false, mergeRange); > continue; > } > > // Remember the merge style unless an addition > if (merge && nextStart < newEnd) > mergeRange = (StyleRange) fRanges.get(index); > > // Make space for a new range if necessary, set delete length > if (nextEnd > newEnd) { > insertSpace(index); > > if (nextStart < newEnd) { > deleteStart = nextStart; > deleteLength = newEnd - nextStart; > } > } > > // If no residual or merge, replace/merge the range, set delete length > if (! merge || newEnd <= nextEnd) { > setRange(index, newRange, newStart, newLength, merge, mergeRange); > deleteStart = nextEnd; > deleteLength = newEnd - nextEnd; > break; > } > > // Do the merge and continue with the residual > setRange(index, newRange, newStart, newLength - nextEnd, merge, mergeRange); > newLength -= newEnd - nextEnd; > newStart = nextEnd; > } > > // Delete any overlapped ranges which follow > index += 1; > while (deleteLength > 0 && index < fRanges.size()) { > int nextStart = fOffsetLengths[index *2]; > int nextLength = fOffsetLengths[index *2 +1]; > > // Update if space before next range > if (deleteStart < nextStart) { > deleteLength -= nextStart - deleteStart; > deleteStart += nextStart - deleteStart; > if (deleteLength <= 0) break; > } > > // Delete the first part of the next range > if (deleteLength < nextLength) { > makeModel(index); > fOffsetLengths[index *2] += deleteLength; > fOffsetLengths[index *2 +1] -= deleteLength; > break; > } > > // Delete the next range if necessary and continue > if (deleteLength >= nextLength ) { > deleteRange(index); > deleteStart += nextLength; > deleteLength -= nextLength; > } > } > } > > /** > * Helper method which converts a specified range to a model > * > * @param index the index of the specified StyleRange > * @return the model range > */ > private StyleRange makeModel(int index) { > StyleRange range = (StyleRange) fRanges.get(index); > StyleRange r = makeModel(range); > > if (range != r) > fRanges.set(index, r); > return r; > } > > /** > * Helper method which converts a range to a model and returns it > * > * @param range the StyleRange to be converted to a model > * @return the model range > */ > private StyleRange makeModel(StyleRange range) { > StyleRange r = range; > > if (r.length > 0) { > r = (StyleRange) range.clone(); > r.start = 0; > r.length = 0; > } > return r; > } > > /** > * Helper method to insert space for a range. This includes expanding the > * offset and length arrays (by 50% plus 50) as necessary. > * > * @param index the position to insert the new dummy range > */ > private void insertSpace(int index) { > int size = fRanges.size() *2; > > if (size >= fOffsetLengths.length) { > int newSize = size + ((size /4) *2) +50; > > int[] temp = new int[newSize]; > System.arraycopy(fOffsetLengths, 0, temp, 0, size); > fOffsetLengths = temp; > } > > int length = size - index *2; > if (length > 0) { > System.arraycopy(fOffsetLengths, index *2, fOffsetLengths, index*2 +2, length); > } > > fRanges.add(index, null); > } > > /** > * Helper method to delete a range > * > * @param index the index of the range to be deleted > */ > private void deleteRange(int index) { > fRanges.remove(index); > > int length = fRanges.size() - index; > if (length > 0) { > System.arraycopy(fOffsetLengths, index *2 + 2, fOffsetLengths, index *2, length *2); > } > } > > /** > * Helper method to set or merge a range > * > * @param index the index of the range > * @param range the new StyleRange > * @param start the starting offset > * @param length the range length > * @param merge <code>true</code> if a merge is to be performed > * @param mergeRange the template range for the merge, if any > */ > private void setRange(int index, StyleRange range, int start, int length > , boolean merge, StyleRange mergeRange) { > > StyleRange newRange = range; > > // If doing a merge, the target must be a new model > if (merge) { > if (mergeRange != null) > newRange = (StyleRange)mergeRange.clone(); > else { > newRange = getDefaultStyleRange(); > if (newRange == null) > newRange = (StyleRange) range.clone(); > } > > newRange.start = 0; > newRange.length = 0; > applyStyle(range, newRange, true); > } > > fRanges.set(index, newRange); > fOffsetLengths[index *2] = start; > fOffsetLengths[index *2 +1] = length; > } > > /** > * 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, boolean merge) { > for (int i= 0, n= ranges.length; i < n; i++) { > applyStyleRange(ranges[i], merge); > } > } > > /** > * 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, boolean merge) { > if (merge) { > if (template.font != null) > target.font= template.font; > target.fontStyle|= template.fontStyle; > > if (template.metrics != null) > target.metrics= template.metrics; > > if (template.foreground != null || template.underlineStyle == SWT.UNDERLINE_LINK) > target.foreground= template.foreground; > if (template.background != null) > target.background= template.background; > > target.strikeout|= template.strikeout; > if (template.strikeoutColor != null) > target.strikeoutColor= template.strikeoutColor; > > target.underline|= template.underline; > if (template.underlineStyle != SWT.NONE && target.underlineStyle != SWT.UNDERLINE_LINK) > target.underlineStyle= template.underlineStyle; > > if (template.underlineColor != null) > target.underlineColor= template.underlineColor; > > if (template.borderStyle != SWT.NONE) > target.borderStyle= template.borderStyle; > if (template.borderColor != 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 > * @param start the starting offset > * @param length the StyleRange length > * > * @exception IllegalArgumentException if range is not a subrange of the presentation's default range > */ > private void checkConsistency(StyleRange range, int start, int length) { > > if (range == null || start < 0 || length <= 0) > throw new IllegalArgumentException(); > > if (fDefaultRange != null) { > > if (start < fDefaultRange.start) > throw new IllegalArgumentException(); > > > int defaultEnd= start + length; > int end= start + length; > if (end > defaultEnd) > throw new IllegalArgumentException(); > } > } > > /** > * 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 != null) { > return getFirstIndexAtOffset(window.getOffset()); > } > return 0; > } > > /** > * Returns the index of the first range which overlaps with the > * specified offset. > * > * @param start the offset to be used for searching > * @return the index of the first range overlapping with the offset > */ > private int getFirstIndexAtOffset(int start) { > int i= -1, j= fRanges.size(); > while (j - i > 1) { > int k= (i + j) >> 1; > > if (fOffsetLengths[k *2] + fOffsetLengths[k *2 +1] > start) > j= k; > else > i= k; > } > return j; > } > > /** > * 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 != null) { > return getFirstIndexAfterOffset(window.getOffset() + window.getLength()); > > } > return fRanges.size(); > } > > /** > * Returns the index of the first range which comes after the specified offset. > * > * @param end the offset to be used for searching > * @return the index of the first range following the ending offset > */ > private int getFirstIndexAfterOffset(int end) { > int i= -1, j= fRanges.size(); > while (j - i > 1) { > int k= (i + j) >> 1; > if (fOffsetLengths[k *2] < end) > i= k; > else > j= k; > } > return j; > } > > /** > * 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 (range == null) > return range; > > return createWindowRelativeRange(window, range, range.start, range.length); > > } > > /** > * 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 > * @param offset the offset the range > * @param length the length the range > * @return the window relative range based on the absolute range > */ > private StyleRange createWindowRelativeRange(IRegion window, StyleRange range, int offset, int length) { > if (range == null) > return range; > > int start = offset; > int end = offset + length; > > if (window != null) { > start = offset - window.getOffset(); > if (start < 0) > start= 0; > > int rangeEnd = offset + length; > int windowEnd= window.getOffset() + window.getLength(); > end= (rangeEnd > windowEnd ? windowEnd : rangeEnd); > end -= window.getOffset(); > } > > if (start == range.start && end - start == range.length) return range; > > StyleRange newRange= (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 == null || coverage == 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(); > > if (start == coverage.getOffset() && end - start == coverage.getLength()) > return coverage; > > 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 != 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 an iterator which enumerates all StyleRange objects > * as clipped by the result window. > * > * <p> Each StyleRange returned may or may not be a model, with a > * zero starting offset and length. > * > * <p> The iterator also provides: > * <ul> > * <li> <code>getOffset()</code> which returns the range offset > * <li> <code>getLength()</code> which returns the range length > * </ul> > * @return an iterator which enumerates all StyleRange objects > * as clipped by the result window. > */ > public StyleRangeIterator getStyleRangeModelIterator() { > return new StyleRangeIterator(); > } > > /** > * 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 boolean isEmpty() { > return (fDefaultRange == null && getDenumerableRanges() == 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 { > > int index = getFirstIndexInWindow(fResultWindow); > StyleRange range = (StyleRange) fRanges.get(index); > return createWindowRelativeRange(fResultWindow, range, fOffsetLengths[index *2], fOffsetLengths[index *2 +1]); > > } 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 { > > int index = getFirstIndexAfterWindow(fResultWindow) - 1; > StyleRange range = (StyleRange) fRanges.get(index); > return createWindowRelativeRange(fResultWindow, range, fOffsetLengths[index *2], fOffsetLengths[index *2 +1]); > > } 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 != null) { > StyleRange range= getDefaultStyleRange(); > return new Region(range.start, range.length); > } > > StyleRange first= getFirstStyleRange(); > StyleRange last= getLastStyleRange(); > > if (first == null || last == 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 != 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(); > } > > >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 119384
:
175181
| 175676 |
175677