All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.swt.custom.StyledTextWriterBase Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (c) 2000, 2022 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.custom;

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;

/**
 * The base class encapsulating the logic used to write styled content as
 * a rich format (HTML, RTF, maybe more). It contains the common parts:
 * iterates on lines, then on each line iterates on plain text and {@link StyleRange}(s).
 *
 * 

{@code toString()} is guaranteed to return a valid formatted string only after * {@code close()} has been called.

* *

Whole and partial lines and line breaks can be written. Lines will be * formatted using the styles queried from the {@link LineStyleListener}, * if set, or those set directly in the widget. All styles are applied to * the stream like they are rendered by the widget. In addition, the * widget font name and size is used for the whole text.

*/ abstract class StyledTextWriterBase extends TextWriter { final StyledText styledText; /** * Creates a writer that processed content starting at offset "start" * in the document. {@code start} and {@code length} can be set to specify * partial lines. * * @param start start offset of content to write, 0 based from beginning of document * @param length length of content to write * @param styledText the widget to produce the RTF from */ public StyledTextWriterBase(StyledText styledText, int start, int length) { super(start, length); this.styledText = styledText; } /** * Appends the specified segment of "string" to the output data. * Copy from {@code start} up to, but excluding, {@code end}. * * @param string string to copy a segment from. Must not contain line breaks. * Line breaks should be written using {@link #writeLineDelimiter()} * @param start start offset of segment. 0 based. * @param end end offset of segment */ void writeEscaped(String string, int start, int end) { String textToWrite = string.substring(start, end); write(escapeText(textToWrite)); } /** * Appends the specified line text to the output data. Lines will be formatted * using the styles queried from the LineStyleListener, if set, or those set * directly in the widget. * * @param line line text to write. Must not contain line breaks * Line breaks should be written using {@link #writeLineDelimiter(String)} * @param lineOffset offset of the line. 0 based from the start of the * widget document. Any text occurring before the start offset or after the * end offset specified during object creation is ignored. * * @throws SWTException {@code ERROR_IO} when the writer is closed. */ @Override public void writeLine(String line, int lineOffset) { if (isClosed()) { SWT.error(SWT.ERROR_IO); } int lineIndex = styledText.content.getLineAtOffset(lineOffset); int lineAlignment; int lineIndent; boolean lineJustify; int verticalIndent; int[] ranges; StyleRange[] styles; StyledTextEvent event = styledText.getLineStyleData(lineOffset, line); if (event != null) { verticalIndent = event.verticalIndent; lineAlignment = event.alignment; lineIndent = event.indent; lineJustify = event.justify; ranges = event.ranges; styles = event.styles; } else { verticalIndent = styledText.renderer.getLineVerticalIndent(lineIndex); lineAlignment = styledText.renderer.getLineAlignment(lineIndex, styledText.alignment); lineIndent = styledText.renderer.getLineIndent(lineIndex, styledText.indent); lineJustify = styledText.renderer.getLineJustify(lineIndex, styledText.justify); ranges = styledText.renderer.getRanges(lineOffset, line.length()); styles = styledText.renderer.getStyleRanges(lineOffset, line.length(), false); } if (styles == null) { styles = new StyleRange[0]; } event = styledText.getLineBackgroundData(lineOffset, line); Color lineBackground = (event != null && event.lineBackground != null) ? event.lineBackground : styledText.renderer.getLineBackground(lineIndex, null); writeStyledLine(line, lineOffset, ranges, styles, lineBackground, lineIndent, verticalIndent, lineAlignment, lineJustify); } /** * Appends the specified line text to the output data. * *

Use the colors and font styles specified in {@code styles} and {@code lineBackground}. * Formatting is written to reflect the text rendering by the text widget. * Style background colors take precedence over the line background color.

* * @param line line text to write as RTF. Must not contain line breaks * Line breaks should be written using writeLineDelimiter() * @param lineOffset offset of the line. 0 based from the start of the * widget document. Any text occurring before the start offset or after the * end offset specified during object creation is ignored. * @param styles styles to use for formatting. Must not be null. * @param lineBackground line background color to use for formatting. * May be null. */ void writeStyledLine(String line, int lineOffset, int ranges[], StyleRange[] styles, Color lineBackground, int indent, int verticalIndent, int alignment, boolean justify) { int lineLength = line.length(); int startOffset = getStart(); int writeOffset = startOffset - lineOffset; if (writeOffset >= lineLength) { return; } int lineIndex = Math.max(0, writeOffset); String atLineEnd = writeLineStart(lineBackground, indent, verticalIndent, alignment, justify); int endOffset = startOffset + super.getCharCount(); // We are already at the end, should not write an empty paragraph if (lineOffset >= endOffset) { return; } int lineEndOffset = Math.min(lineLength, endOffset - lineOffset); int outTextLen = 0; // collect the length of the text we output (unescaped) for (int i = 0; i < styles.length; i++) { StyleRange style = styles[i]; int start, end; if (ranges != null) { start = ranges[i << 1] - lineOffset; end = start + ranges[(i << 1) + 1]; } else { start = style.start - lineOffset; end = start + style.length; } // skip over partial first line if (end < writeOffset) { continue; } // style starts beyond line end or write end if (start >= lineEndOffset) { break; } // write any unstyled text if (lineIndex < start) { // copy to start of style // style starting beyond end of write range or end of line // is guarded against above. writeEscaped(line, lineIndex, start); outTextLen += start - lineIndex; lineIndex = start; } // write styled text String atSpanEnd = writeSpanStart(style); // copy to end of style or end of write range or end of line int copyEnd = Math.min(end, lineEndOffset); // guard against invalid styles and let style processing continue copyEnd = Math.max(copyEnd, lineIndex); writeEscaped(line, lineIndex, copyEnd); outTextLen += copyEnd - lineIndex; writeSpanEnd(atSpanEnd); lineIndex = copyEnd; } // write the unstyled text at the end of the line if (lineIndex < lineEndOffset) { writeEscaped(line, lineIndex, lineEndOffset); outTextLen += lineEndOffset - lineIndex; } if (outTextLen == 0) { writeEmptyLine(); } writeLineEnd(atLineEnd); } /** * Writes the part that only shows once, at the beginning of the output data. */ abstract void writeHeader(); /** * Takes plain text and returns the same text escaped using the rules of the output format. * @param text the text to escape * @return the escaped text */ abstract String escapeText(String text); /** * Invoked at the beginning of each line in the original widget. * *

It should output whatever tags are appropriate to start a new line in the output format.
* It will return the text that has to be output at the end of the line.

* * @return the text to append at the end of the line */ abstract String writeLineStart(Color lineBackground, int indent, int verticalIndent, int alignment, boolean justify); /** * Invoked at the end of of each line in the original widget. * *

It receives whatever text {@link #writeLineStart(Color,int,int,int,boolean)} returned * and it will output it. A class might override it to do more.

* * @param prepared the leftover text prepared by {@code writeLineStart} */ void writeLineEnd(String prepared) { write(prepared); } /** * Invoked at the end of each line, writeLineEnd, if there was no text output. * *

This is needed for HTML, which does not render empty paragraphs.

*/ abstract void writeEmptyLine(); /** * Invoked at the beginning of each styled span fragment in the original widget. * *

It should output whatever tags are appropriate to start a formatted span in the output format.
* It will return the text that has to be output at the end of the span (to close it).

* * @return the text to append at the end of the styled span */ abstract String writeSpanStart(StyleRange style); /** * Invoked at the end of of each styled span fragment in the original widget. * *

It receives whatever text {@link #writeSpanStart(StyleRange)} returned * and it will output it. A class might override it to do more.

* * @param prepared the leftover text prepared by {@code writeSpanStart} */ void writeSpanEnd(String prepared) { write(prepared); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy