Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/WrappedContent.java')
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/WrappedContent.java653
1 files changed, 0 insertions, 653 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/WrappedContent.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/WrappedContent.java
deleted file mode 100644
index bf05aadb17..0000000000
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/WrappedContent.java
+++ /dev/null
@@ -1,653 +0,0 @@
-package org.eclipse.swt.custom;
-/*
- * (c) Copyright IBM Corp. 2001, 2002.
- * All Rights Reserved
- */
-
-import org.eclipse.swt.*;
-import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.internal.*;
-
-/**
- * An instance of class <code>WrappedContent</code> is used by
- * StyledText to display wrapped lines. Lines are wrapped at word
- * breaks which are marked by a space character. Trailing space
- * behind words is kept on the current line.
- * If the last remaining word on a line can not be fully displayed
- * the line is wrapped character by character.
- * WrappedContent wraps a StyledTextContent which provides the line
- * data. The start offset and length of wrapped lines is calculated
- * and updated based on recalculation requests and text changes.
- * <p>
- * All public methods in this class implement the
- * <code>StyledTextContent</code> interface. Package visible
- * methods are internal API for use by <code>StyledText</code>.
- * </p>
- */
-class WrappedContent implements StyledTextContent {
- final static int LINE_OFFSET = 0; // index of line offset in visualLines array
- final static int LINE_LENGTH = 1; // index of line lenght in visualLines array
- final static int WRAP_LINE_LENGTH = 0;
- final static int WRAP_LINE_WIDTH = 1;
-
- StyledText parent;
- StyledTextContent logicalContent;
- int[][] visualLines; // start and length of each visual line
- int visualLineCount = 0;
-
-/**
- * Create a new instance.
- *
- * @param styledText StyledText widget that displays the lines
- * wrapped by the new instance.
- * @param logicalContent StyledTextContent that provides the line
- * data.
- */
-WrappedContent(StyledText styledText, StyledTextContent logicalContent) {
- parent = styledText;
- this.logicalContent = logicalContent;
-}
-/**
- * @see StyledTextContent#addTextChangeListener(TextChangeListener)
- */
-public void addTextChangeListener(TextChangeListener listener) {
- logicalContent.addTextChangeListener(listener);
-}
-/**
- * Grow the lines array to at least the specified size.
- * <p>
- *
- * @param numLines number of elements that the array should have
- * at a minimum
- */
-private void ensureSize(int numLines) {
- int size = visualLines.length;
- if (size >= numLines) {
- return;
- }
- int[][] newLines = new int[Math.max(size * 2, numLines)][2];
- System.arraycopy(visualLines, 0, newLines, 0, size);
- visualLines = newLines;
- resetVisualLines(size, visualLines.length - size);
-}
-/**
- * @see StyledTextContent#getCharCount()
- */
-public int getCharCount() {
- return logicalContent.getCharCount();
-}
-/**
- * @return the visual (wrapped) line at the specified index
- * @see StyledTextContent#getLine(int)
- */
-public String getLine(int lineIndex) {
- String line;
-
- // redirect call to logical content if there are no wrapped lines
- if (visualLineCount == 0) {
- line = logicalContent.getLine(lineIndex);
- }
- else {
- line = logicalContent.getTextRange(visualLines[lineIndex][LINE_OFFSET], visualLines[lineIndex][LINE_LENGTH]);
- }
- return line;
-}
-/**
- * Returns the visual (wrapped) line at given offset.
- * <p>
- * The offset is ambiguous if it identifies the end of a visual line and
- * there is another visual line below. In this case the end of the visual
- * line has the same offset as the beginning of the next visual line
- * since the visual line break is not represented by any character in the
- * logical line.
- * In this ambiguous case the offset is assumed to represent the end of a
- * visual line and the index of the first visual line is returned.
- * </p>
- *
- * @param offset offset of the desired line.
- * @return the index of the visual (wrapped) line at the specified offset
- * @see StyledTextContent#getLineAtOffset(int)
- */
-public int getLineAtOffset(int offset) {
- int lastLine = visualLineCount - 1;
- int lastChar;
-
- // redirect call to logical content if there are no wrapped lines
- if (visualLineCount == 0) {
- return logicalContent.getLineAtOffset(offset);
- }
- // can't use getCharCount to get the number of characters since this
- // method is called in textChanged, when the logicalContent used by
- // getCharCount has already changed. at that point the visual lines
- // have not been updated yet and we thus need to use the old character
- // count which is only available in the visual content.
- lastChar = visualLines[lastLine][LINE_OFFSET] + visualLines[lastLine][LINE_LENGTH];
- if (offset < 0 || (offset > 0 && offset > lastChar)) {
- SWT.error(SWT.ERROR_INVALID_ARGUMENT);
- }
- // if last line and the line is not empty you can ask for
- // a position that doesn't exist (the one to the right of the
- // last character) - for inserting
- if (offset == lastChar) {
- return lastLine;
- }
-
- int high = visualLineCount;
- int low = -1;
- int index = visualLineCount;
- while (high - low > 1) {
- index = (high + low) / 2;
- int lineStart = visualLines[index][LINE_OFFSET];
- if (offset >= lineStart) {
- int lineEnd = lineStart + visualLines[index][LINE_LENGTH];
- low = index;
- if (offset <= lineEnd) {
- break;
- }
- }
- else {
- high = index;
- }
- }
- if (low > 0 && offset == visualLines[low - 1][LINE_OFFSET] + visualLines[low - 1][LINE_LENGTH]) {
- // end of a visual line/beginning of next visual line is ambiguous
- // (they have the same offset). always return the first visual line
- low--;
- }
- return low;
-}
-/**
- * @return the number of visual (wrapped) lines
- * @see StyledTextContent#getLineCount()
- */
-public int getLineCount() {
- int lineCount = visualLineCount;
-
- // redirect call to logical content if there are no wrapped lines
- if (visualLineCount == 0) {
- lineCount = logicalContent.getLineCount();
- }
- return lineCount;
-}
-/**
- * @see StyledTextContent#getLineDelimiter()
- */
-public String getLineDelimiter() {
- return logicalContent.getLineDelimiter();
-}
-/**
- * @return the start offset of the visual (wrapped) line at the given
- * index
- * @see StyledTextContent#getOffsetAtLine(int)
- */
-public int getOffsetAtLine(int lineIndex) {
- int offset;
-
- // redirect call to logical content if there are no wrapped lines
- if (visualLineCount == 0) {
- offset = logicalContent.getOffsetAtLine(lineIndex);
- }
- else {
- offset = visualLines[lineIndex][LINE_OFFSET];
- }
- return offset;
-}
-/**
- * @see StyledTextContent#getTextRange(int, int)
- */
-public String getTextRange(int start, int length) {
- return logicalContent.getTextRange(start, length);
-}
-/**
- * Returns the offset of the character after the word at the specified
- * offset.
- * <p>
- * Words are separated by spaces. Trailing spaces are considered part
- * of the word.
- * </p>
- *
- * @param line logical line the word is in
- * @param startOffset start offset of the line, relative to the start
- * of the logical line.
- * @param offset offset of the word to return the end of, relative to
- * the start of the visual line.
- * @return the offset of the character after the word at the specified
- * offset.
- */
-private int getWordEnd(String line, int startOffset, int offset) {
- int lineLength = line.length();
-
- offset += startOffset;
- if (offset >= lineLength) {
- return offset - startOffset;
- }
- // skip over leading whitespace
- do {
- offset++;
- } while (offset < lineLength && Compatibility.isSpaceChar(line.charAt(offset)));
- while (offset < lineLength && Compatibility.isSpaceChar(line.charAt(offset)) == false) {
- offset++;
- }
- // skip over trailing whitespace
- while (offset < lineLength && Compatibility.isSpaceChar(line.charAt(offset))) {
- offset++;
- }
- return offset - startOffset;
-}
-/**
- * Returns the start offset of the word at the specified offset.
- * There are two classes of words formed by a sequence of characters:
- * <p>
- * Words are separated by spaces. Trailing spaces are considered part
- * of the word.
- * </p>
- *
- * @param line logical line the word is in
- * @param startOffset start offset of the line, relative to the start
- * of the logical line.
- * @param offset offset of the word to return the start of, relative to
- * the start of the visual line.
- * @return the start offset of the word at the specified offset.
- */
-private int getWordStart(String line, int startOffset, int offset) {
- offset += startOffset;
- // skip over trailing whitespace
- do {
- offset--;
- } while (offset > startOffset && Compatibility.isSpaceChar(line.charAt(offset)));
- while (offset > startOffset && Compatibility.isSpaceChar(line.charAt(offset - 1)) == false) {
- offset--;
- }
- return offset - startOffset;
-}
-/**
- * @see StyledTextContent#removeTextChangeListener(TextChangeListener)
- */
-public void removeTextChangeListener(TextChangeListener listener) {
- logicalContent.removeTextChangeListener(listener);
-}
-/**
- * Reset the visual (wrapped) lines in the specified range.
- * If the range specifies partial logical lines (e.g., startLine is
- * the second of two visual lines) it is extended to reset all visual
- * lines of a logical line.
- * Following the reset the logical lines in the reset visual range are
- * rewrapped.
- * <p>
- *
- * @param startLine index of the first visual line
- * @param lineCount number of visual lines
- */
-void reset(int startLine, int lineCount) {
- if (lineCount <= 0 || visualLineCount == 0) {
- return;
- }
- reset(startLine, lineCount, true);
-}
-/**
- * Reset the visual (wrapped) lines in the specified range.
- * If the range specifies partial logical lines (e.g., startLine is
- * the second of two visual lines) it is extended to reset all visual
- * lines of a logical line.
- * <p>
- *
- * @param startLine index of the first visual line
- * @param lineCount number of visual lines
- * @param wrap true=rewrap the logical lines in the reset visual range
- * false=don't rewrap lines. Visual lines will be left in an inconsistent
- * state since there will be a range of unwrapped and unknown lines.
- * @return the first visual line that was reset
- */
-private int reset(int startLine, int lineCount, boolean wrap) {
- if (lineCount <= 0) {
- return startLine;
- }
- // make sure that all visual lines of the first logical line are
- // being reset. visualFirstLine is the first visual line of the
- // first logical line that has at least one visual line reset.
- int visualFirstLineOffset = getOffsetAtLine(startLine);
- int logicalFirstLine = logicalContent.getLineAtOffset(visualFirstLineOffset);
- int logicalFirstLineOffset = logicalContent.getOffsetAtLine(logicalFirstLine);
- int visualFirstLine = getLineAtOffset(logicalFirstLineOffset);
-
- lineCount += startLine - visualFirstLine;
- startLine = visualFirstLine;
-
- // make sure that all visual lines of the last logical line are
- // being reset.
- int lastLine = startLine + lineCount - 1;
- int lastLineEnd = visualLines[lastLine][LINE_OFFSET] + visualLines[lastLine][LINE_LENGTH];
- int logicalEndLine = 0;
-
- while (lastLine < visualLineCount - 1 && lastLineEnd == visualLines[lastLine + 1][LINE_OFFSET]) {
- lastLine++;
- lastLineEnd = visualLines[lastLine][LINE_OFFSET] + visualLines[lastLine][LINE_LENGTH];
- }
- if (wrap) {
- if (lastLine == visualLineCount - 1) {
- logicalEndLine = logicalContent.getLineCount();
- }
- else {
- logicalEndLine = logicalContent.getLineAtOffset(visualLines[lastLine + 1][LINE_OFFSET]);
- }
- }
- lineCount = lastLine - startLine + 1;
- resetVisualLines(startLine, lineCount);
- visualLineCount -= lineCount;
- if (wrap) {
- // always recalculate line wrap immediately after a reset
- // because the content always needs to be in a usable state.
- // i.e., there must not be any reset but unwrapped lines
- wrapLineRange(logicalFirstLine, logicalEndLine, startLine);
- }
- return startLine;
-}
-/**
- * Reset the visual (wrapped) lines in the specified range.
- * <p>
- *
- * @param startLine index of the first visual line
- * @param lineCount number of visual lines
- */
-private void resetVisualLines(int startLine, int lineCount) {
- int endLine = startLine + lineCount;
-
- for (int i = startLine; i < endLine; i++) {
- visualLines[i] = new int[] {-1, -1};
- }
-}
-/**
- * @see StyledTextContent#replaceTextRange(int, int, String)
- */
-public void replaceTextRange(int start, int replaceLength, String text) {
- logicalContent.replaceTextRange(start, replaceLength, text);
-}
-/**
- * @see StyledTextContent#setText(String)
- */
-public void setText(String text) {
- logicalContent.setText(text);
-}
-/**
- * Set the line wrap data for the specified visual (wrapped) line.
- * <p>
- *
- * @param visualLineIndex index of the visual line
- * @param visualLineOffset start offset of the visual line, relative
- * to the start of the document
- * @param visualLineLength length of the visual line
- */
-private void setVisualLine(int visualLineIndex, int visualLineOffset, int visualLineLength) {
- ensureSize(visualLineCount + 1);
- // is the space for the visual line already taken? can happen if
- // there are more visual lines for a given logical line than before
- if (visualLines[visualLineIndex][LINE_OFFSET] != -1) {
- System.arraycopy(visualLines, visualLineIndex, visualLines, visualLineIndex + 1, visualLineCount - visualLineIndex);
- visualLines[visualLineIndex] = new int[2];
- }
- visualLines[visualLineIndex][LINE_OFFSET] = visualLineOffset;
- visualLines[visualLineIndex][LINE_LENGTH] = visualLineLength;
- visualLineCount++;
-}
-/**
- * Recalculates the line wrap for the lines affected by the
- * text change.
- * <p>
- *
- * @param startOffset the start offset of the text change
- * @param newLineCount the number of inserted lines
- * @param replaceLineCount the number of deleted lines
- * @param newCharCount the number of new characters
- * @param replaceCharCount the number of deleted characters
- */
-void textChanged(int startOffset, int newLineCount, int replaceLineCount, int newCharCount, int replaceCharCount) {
- // do nothing if there are no wrapped lines
- if (visualLineCount == 0) {
- return;
- }
- int logicalStartLine = logicalContent.getLineAtOffset(startOffset);
- int visualStartLine = getLineAtOffset(startOffset);
- int visualReplaceLastLine = visualLineCount - 1;
- int textChangeDelta = newCharCount - replaceCharCount;
-
- if (replaceLineCount > 0) {
- visualReplaceLastLine = getLineAtOffset(startOffset + replaceCharCount);
- // at the start of a visual line/end of the previous visual line?
- if (visualReplaceLastLine == 0 ||
- visualLines[visualReplaceLastLine][LINE_OFFSET] == visualLines[visualReplaceLastLine - 1][LINE_OFFSET] + visualLines[visualReplaceLastLine - 1][LINE_LENGTH]) {
- visualReplaceLastLine++;
- }
- visualStartLine = reset(visualStartLine, visualReplaceLastLine - visualStartLine + 1, false);
- }
- else {
- visualStartLine = reset(visualStartLine, 1, false);
- }
- visualReplaceLastLine = wrapLineRange(logicalStartLine, logicalStartLine + 1 + newLineCount, visualStartLine);
- for (int i = visualReplaceLastLine; i < visualLineCount; i++) {
- visualLines[i][LINE_OFFSET] += textChangeDelta;
- }
-}
-/**
- * Measure the width of a segment in the specified logical line.
- * <p>
- *
- * @param line the logical line
- * @param logicalLineOffset start offset of the logical line, relative
- * to the start of the document
- * @param visualLineOffset offset to start measuring at/start offset
- * of the visual line
- * @param visualLineLength length of the segment to measure/the visual
- * line
- * @param styles StyleRanges to use during measuring
- * @param startX x position of the visual line relative to the start
- * of the logical line
- * @param gc GC to use for measuring
- * @param fontData FontData currently set in gc. Used to reduce calls
- * to gc.getFont().getFontData()
- */
-private int textWidth(String line, int logicalLineOffset, int visualLineOffset, int visualLineLength, StyleRange[] styles, int startX, GC gc, FontData fontData) {
- int width;
-
- if (styles != null) {
- // while wrapping a line, the logcial line styles may contain
- // style ranges that don't apply (i.e., completely on the previous/next
- // visual line). Therefore we need to filter the logical lines.
- styles = parent.getVisualLineStyleData(styles, logicalLineOffset + visualLineOffset, visualLineLength);
- }
- if (parent.isBidi()) {
- String wrappedLine = line.substring(visualLineOffset, visualLineOffset + visualLineLength);
- StyledTextBidi bidi = parent.getStyledTextBidi(wrappedLine, logicalLineOffset + visualLineOffset, gc, styles);
- width = bidi.getTextWidth();
- }
- else {
- width = parent.textWidth(line, logicalLineOffset, visualLineOffset, visualLineLength, styles, startX, gc, fontData);
- }
- return width;
-}
-/**
- * Wrap the given logical line at the specified offset.
- * Called repeatedly until the entire logical lines has been split into
- * visual (wrapped) lines.
- * <p>
- *
- * @param line the logical line
- * @param logicalLineOffset offset of the logical line, relative to the
- * beginning of the content
- * @param visualLineOffset start offset of the new visual line, relative
- * to the start of the logical line.
- * @param startX x position of visualLineOffset, relative to the beginning
- * of the logical line
- * @param width width to wrap the line to
- * @param numChars average number of characters that fit into width
- * @param styles StyleRanges to use for measuring the wrapped line
- * @param gc GC to use for measuring
- * @param fontData FontData currently set in gc. Used to reduce calls to
- * gc.getFont().getFontData()
- * @return int[0]=length of the new visual line, int[1]=width in pixels
- * of the new visual line
- */
-private int[] wrapLine(String line, int logicalLineOffset, int visualLineOffset, int startX, int width, int numChars, StyleRange[] styles, GC gc, FontData fontData) {
- int lineLength = line.length();
- int lineWidth = 0;
- int visualLineLength;
-
- numChars = Math.min(numChars, lineLength - visualLineOffset);
- visualLineLength = getWordStart(line, visualLineOffset, numChars);
- // find a word that is within the client area. make sure at least one
- // character is on each line so that line wrap algorithm terminates.
- if (visualLineLength > 0) {
- lineWidth = textWidth(line, logicalLineOffset, visualLineOffset, visualLineLength, styles, startX, gc, fontData);
- if (lineWidth >= width) {
- while (visualLineLength > 1 && lineWidth >= width) {
- visualLineLength = getWordStart(line, visualLineOffset, visualLineLength);
- lineWidth = textWidth(line, logicalLineOffset, visualLineOffset, visualLineLength, styles, startX, gc, fontData);
- }
- }
- else
- if (lineWidth < width) {
- while (visualLineOffset + visualLineLength < lineLength) {
- int newLineLength = getWordEnd(line, visualLineOffset, visualLineLength);
- int newLineWidth = textWidth(line, logicalLineOffset, visualLineOffset, newLineLength, styles, startX, gc, fontData);
- // would next word be beyond client area?
- if (newLineWidth >= width) {
- break;
- }
- else {
- visualLineLength = newLineLength;
- lineWidth = newLineWidth;
- }
- }
- }
- }
- if (visualLineLength <= 0) {
- // no complete word fits on the line. either first word was not within
- // estimated number of characters or it was beyond the line width even
- // though it was within numChars.
- visualLineLength = numChars;
- lineWidth = textWidth(line, logicalLineOffset, visualLineOffset, visualLineLength, styles, startX, gc, fontData);
- if (lineWidth >= width) {
- while (visualLineLength > 1 && lineWidth >= width) {
- visualLineLength--;
- lineWidth = textWidth(line, logicalLineOffset, visualLineOffset, visualLineLength, styles, startX, gc, fontData);
- }
- }
- else
- if (lineWidth < width) {
- while (visualLineOffset + visualLineLength < lineLength) {
- int newLineWidth = textWidth(line, logicalLineOffset, visualLineOffset, visualLineLength + 1, styles, startX, gc, fontData);
- if (newLineWidth >= width) {
- break;
- }
- else {
- visualLineLength++;
- lineWidth = newLineWidth;
- }
- }
- }
- }
- return new int[] {visualLineLength, lineWidth};
-}
-/**
- * Wrap the logical lines in the given range at the current client
- * area width of the StyledText widget
- * <p>
- *
- * @param startLine first logical line to wrap
- * @param endLine line after last logical line
- * @param visualLineIndex visual (wrapped) line index that startLine
- * corresponds to.
- * @return index of the line following the last wrapped line
- */
-private int wrapLineRange(int startLine, int endLine, int visualLineIndex) {
- int emptyLineCount = 0;
-
- visualLineIndex = wrapLineRange(startLine, endLine, visualLineIndex, parent.getClientArea().width);
- // is there space left for more visual lines? can happen if there are fewer
- // visual lines for a given logical line than before
- for (int i = visualLineIndex; i < visualLines.length; i++, emptyLineCount++) {
- if (visualLines[i][LINE_OFFSET] != -1) {
- break;
- }
- }
- if (emptyLineCount > 0) {
- int copyLineCount = visualLineCount - visualLineIndex;
- System.arraycopy(visualLines, visualLineIndex + emptyLineCount, visualLines, visualLineIndex, copyLineCount);
- resetVisualLines(visualLineIndex + copyLineCount, emptyLineCount);
- }
- return visualLineIndex;
-}
-/**
- * Wrap the lines in the given range. Skip lines that have already
- * been wrapped.
- * <p>
- *
- * @param startLine first logical line to wrap
- * @param endLine line after last logical line
- * @param visualLineIndex visual (wrapped) line index that startLine
- * corresponds to.
- * @param width line width to wrap at
- * @return index of last wrapped line
- */
-private int wrapLineRange(int startLine, int endLine, int visualLineIndex, int width) {
- GC gc = new GC(parent);
- FontData fontData = gc.getFont().getFontData()[0];
- int numChars = Math.max(1, width / gc.getFontMetrics().getAverageCharWidth());
-
- // if there are no wrapped lines and the width is 0 the widget has
- // not been made visible/sized yet. don't wrap until the widget size
- // is known.
- if (visualLineCount == 0 && width == 0) {
- return visualLineIndex;
- }
- for (int i = startLine; i < endLine; i++) {
- String line = logicalContent.getLine(i);
- int lineOffset = logicalContent.getOffsetAtLine(i);
- int lineLength = line.length();
-
- if (lineLength == 0) {
- setVisualLine(visualLineIndex, lineOffset, 0);
- visualLineIndex++;
- continue;
- }
- StyleRange[] styles = null;
- StyledTextEvent event = parent.getLineStyleData(lineOffset, line);
- int startOffset = 0;
- int startX = 0;
-
- if (event != null) {
- styles = parent.filterLineStyles(event.styles);
- }
- while (startOffset < lineLength) {
- int[] result = wrapLine(line, lineOffset, startOffset, startX, width, numChars, styles, gc, fontData);
-
- setVisualLine(visualLineIndex, lineOffset + startOffset, result[WRAP_LINE_LENGTH]);
- startOffset += result[WRAP_LINE_LENGTH];
- startX += result[WRAP_LINE_WIDTH];
- visualLineIndex++;
- }
- }
- gc.dispose();
- return visualLineIndex;
-}
-/**
- * Wrap all logical lines at the current client area width of the
- * StyledText widget
- */
-void wrapLines() {
- wrapLines(parent.getClientArea().width);
-}
-/**
- * Wrap all logical lines at the given width.
- * <p>
- *
- * @param width width to wrap lines at
- */
-void wrapLines(int width) {
- int lineCount = logicalContent.getLineCount();
-
- visualLineCount = 0;
- visualLines = new int[lineCount][2];
- resetVisualLines(0, visualLines.length);
- wrapLineRange(0, lineCount, 0, width);
-}
-} \ No newline at end of file

Back to the top