blob: 800c03b4abb625c4bbd7262e26f730d1a1cd4cbd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.swt.custom;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
/**
* A StyledTextRenderer renders the content of a StyledText widget.
* Subclasses can provide a different device (e.g., Display, Printer)
* to render on and implement abstract methods to return resources
* created on that device.
*/
abstract class StyledTextRenderer {
private Device device; // device to render on
protected Font regularFont;
protected Font boldFont;
private boolean isBidi;
private int leftMargin;
private int tabLength; // length in space characters of a tab character
private int tabWidth; // width in pixels of a tab character
private int lineHeight; // height in pixels of a line
private int lineEndSpaceWidth; // width in pixels of the space used to represent line delimiters
private int currentFontStyle = SWT.NORMAL;
/**
* Creates an instance of <class>StyledTextRenderer</class>.
* </p>
* @param device Device to render on
* @param regularFont Font to use for regular (non-bold) text
* @param isBidi true=bidi platform, false=no bidi platform
* @param leftMargin margin to the left of the text
*/
StyledTextRenderer(Device device, Font regularFont, boolean isBidi, int leftMargin) {
FontData[] fontDatas = regularFont.getFontData();
for (int i = 0; i < fontDatas.length; i++) {
fontDatas[i].setStyle(fontDatas[i].getStyle() | SWT.BOLD);
}
boldFont = new Font(device, fontDatas);
this.device = device;
this.regularFont = regularFont;
this.isBidi = isBidi;
this.leftMargin = leftMargin;
}
/**
* Calculates the line height and space width.
*/
void calculateLineHeight() {
GC gc = getGC();
lineHeight = gc.getFontMetrics().getHeight();
lineEndSpaceWidth = gc.stringExtent(" ").x;
disposeGC(gc);
}
/**
* Disposes the resource created by the receiver.
*/
void dispose() {
if (boldFont != null) {
boldFont.dispose();
boldFont = null;
}
}
/**
* Dispose the specified GC.
* Allows subclasses to reuse GCs.
* </p>
* @param gc GC to dispose.
*/
protected abstract void disposeGC(GC gc);
/**
* Draws a line of text at the specified location.
* </p>
*
* @param line the line to draw
* @param lineIndex index of the line to draw
* @param paintY y location to draw at
* @param gc GC to draw on
* @param widgetBackground the widget background color.
* Used as the default rendering color.
* @param widgetForeground the widget foreground color.
* Used as the default rendering color.
* @param clearBackground true if the line background should be drawn
* explicitly.
*/
void drawLine(String line, int lineIndex, int paintY, GC gc, Color widgetBackground, Color widgetForeground, boolean clearBackground) {
int lineOffset = getContent().getOffsetAtLine(lineIndex);
int lineLength = line.length();
Point selection = getSelection();
int selectionStart = selection.x;
int selectionEnd = selection.y;
StyleRange[] styles = new StyleRange[0];
Color lineBackground = null;
StyledTextEvent event = getLineStyleData(lineOffset, line);
StyledTextBidi bidi = null;
if (event != null) {
styles = event.styles;
}
if (isBidi()) {
setLineFont(gc, SWT.NORMAL);
bidi = getStyledTextBidi(line, lineOffset, gc, styles);
}
event = getLineBackgroundData(lineOffset, line);
if (event != null) {
lineBackground = event.lineBackground;
}
if (lineBackground == null) {
lineBackground = widgetBackground;
}
if (clearBackground &&
(isFullLineSelection() == false ||
selectionStart > lineOffset ||
selectionEnd <= lineOffset + lineLength)) {
// draw background if full selection is off or if line is not
// completely selected
gc.setBackground(lineBackground);
gc.setForeground(lineBackground);
gc.fillRectangle(leftMargin, paintY, getClientArea().width, lineHeight);
}
if (selectionStart != selectionEnd) {
drawLineBreakSelection(line, lineOffset, styles, paintY, gc, bidi);
if ((selectionStart >= lineOffset && selectionStart < lineOffset + lineLength) ||
(selectionStart < lineOffset && selectionEnd > lineOffset)) {
styles = mergeSelectionLineStyles(styles);
}
}
drawStyledLine(line, lineOffset, 0, styles, 0, paintY, gc, lineBackground, widgetForeground, bidi);
}
/**
* Draws the background of the line selection.
* Implemented by subclasses for optional selection rendering.
* </p>
*
* @param line the line to draw
* @param lineOffset offset of the first character in the line.
* Relative to the start of the document.
* @param styles line styles
* @param paintY y location to draw at
* @param gc GC to draw on
* @param bidi the bidi object to use for measuring and rendering text in bidi
* locales. null when not in bidi mode.
*/
protected abstract void drawLineBreakSelection(String line, int lineOffset, StyleRange[] styles, int paintY, GC gc, StyledTextBidi bidi);
/**
* Draws the line at the specified location.
* </p>
*
* @param line the line to draw
* @param lineOffset offset of the first character in the line.
* Relative to the start of the document.
* @param renderOffset offset of the first character that should
* be rendered. Relative to the start of the line.
* @param styles the styles to use for rendering line segments.
* May be empty but not null.
* @param paintX x location to draw at, not used in bidi mode
* @param paintY y location to draw at
* @param gc GC to draw on
* @param lineBackground line background color, used when no style
* is specified for a line segment.
* @param lineForeground line foreground color, used when no style
* is specified for a line segment.
* @param bidi the bidi object to use for measuring and rendering text in bidi
* locales. null when not in bidi mode.
*/
private void drawStyledLine(String line, int lineOffset, int renderOffset, StyleRange[] styles, int paintX, int paintY, GC gc, Color lineBackground, Color lineForeground, StyledTextBidi bidi) {
int lineLength = line.length();
int horizontalScrollOffset = getHorizontalPixel();
Color background = gc.getBackground();
Color foreground = gc.getForeground();
StyleRange style = null;
StyleRange[] filteredStyles = filterLineStyles(styles);
int renderStopX = getClientArea().width + horizontalScrollOffset;
// Always render the entire line when in a bidi locale.
// Since we render the line in logical order we may start past the end
// of the visual right border of the client area and work towards the
// left.
for (int i = 0; i < styles.length && (paintX < renderStopX || bidi != null); i++) {
int styleLineLength;
int styleLineStart;
int styleLineEnd;
style = styles[i];
styleLineEnd = style.start + style.length - lineOffset;
styleLineStart = Math.max(style.start - lineOffset, 0);
// render unstyled text between the start of the current
// style range and the end of the previously rendered
// style range
if (styleLineStart > renderOffset) {
background = setLineBackground(gc, background, lineBackground);
foreground = setLineForeground(gc, foreground, lineForeground);
setLineFont(gc, SWT.NORMAL);
// don't try to render more text than requested
styleLineStart = Math.min(lineLength, styleLineStart);
paintX = drawText(line, renderOffset, styleLineStart - renderOffset, paintX, paintY, gc, bidi);
renderOffset = styleLineStart;
}
else
if (styleLineEnd <= renderOffset) {
// style ends before render start offset
// skip to the next style
continue;
}
if (styleLineStart >= lineLength) {
// there are line styles but no text for those styles
// possible when called with partial line text
break;
}
styleLineLength = Math.min(styleLineEnd, lineLength) - renderOffset;
// set style background color if specified
if (style.background != null) {
background = setLineBackground(gc, background, style.background);
foreground = setLineForeground(gc, foreground, style.background);
if (bidi != null) {
bidi.fillBackground(renderOffset, styleLineLength, leftMargin - horizontalScrollOffset, paintY, lineHeight);
}
else {
int fillWidth = getTextWidth(line, lineOffset, renderOffset, styleLineLength, filteredStyles, paintX, gc);
gc.fillRectangle(paintX - horizontalScrollOffset + leftMargin, paintY, fillWidth, lineHeight);
}
}
else {
background = setLineBackground(gc, background, lineBackground);
}
// set style foreground color if specified
if (style.foreground != null) {
foreground = setLineForeground(gc, foreground, style.foreground);
}
else {
foreground = setLineForeground(gc, foreground, lineForeground);
}
setLineFont(gc, style.fontStyle);
paintX = drawText(line, renderOffset, styleLineLength, paintX, paintY, gc, bidi);
renderOffset += styleLineLength;
}
// render unstyled text at the end of the line
if ((style == null || renderOffset < lineLength) &&
(paintX < renderStopX || bidi != null)) {
setLineBackground(gc, background, lineBackground);
setLineForeground(gc, foreground, lineForeground);
setLineFont(gc, SWT.NORMAL);
drawText(line, renderOffset, lineLength - renderOffset, paintX, paintY, gc, bidi);
}
}
/**
* Draws the text at the specified location. Expands tabs to tab
* stops using the widget tab width.
* </p>
*
* @param text text to draw
* @param startOffset offset of the first character in text to draw
* @param length number of characters to draw
* @param paintX x location to start drawing at, not used in bidi mode
* @param paintY y location to draw at. Unused when draw is false
* @param gc GC to draw on
* location where drawing would stop
* @param bidi the bidi object to use for measuring and rendering
* text in bidi locales. null when not in bidi mode.
* @return x location where drawing stopped or 0 if the startOffset or
* length is outside the specified text. In bidi mode this value is
* the same as the paintX input parameter.
*/
private int drawText(String text, int startOffset, int length, int paintX, int paintY, GC gc, StyledTextBidi bidi) {
int endOffset = startOffset + length;
int textLength = text.length();
int horizontalScrollOffset = getHorizontalPixel();
if (startOffset < 0 || startOffset >= textLength || startOffset + length > textLength) {
return paintX;
}
for (int i = startOffset; i < endOffset; i++) {
int tabIndex = text.indexOf(StyledText.TAB, i);
// is tab not present or past the rendering range?
if (tabIndex == -1 || tabIndex > endOffset) {
tabIndex = endOffset;
}
if (tabIndex != i) {
if (bidi != null) {
bidi.drawBidiText(i, tabIndex - i, leftMargin - horizontalScrollOffset, paintY);
}
else {
String tabSegment = text.substring(i, tabIndex);
gc.drawString(tabSegment, paintX - horizontalScrollOffset + leftMargin, paintY, true);
paintX += gc.stringExtent(tabSegment).x;
if (tabIndex != endOffset && tabWidth > 0) {
paintX = getTabStop(paintX);
}
}
i = tabIndex;
}
else // is tab at current rendering offset?
if (tabWidth > 0 && isBidi() == false) {
paintX = getTabStop(paintX);
}
}
return paintX;
}
/**
* Filter the given style ranges based on the font style and
* return the unchanged styles only if there is at least one
* non-regular (e.g., bold) font.
* </p>
*
* @param styles styles that may contain font styles.
* @return null if the styles contain only regular font styles, the
* unchanged styles otherwise.
*/
StyleRange[] filterLineStyles(StyleRange[] styles) {
if (styles != null) {
int styleIndex = 0;
while (styleIndex < styles.length && styles[styleIndex].fontStyle == SWT.NORMAL) {
styleIndex++;
}
if (styleIndex == styles.length) {
styles = null;
}
}
return styles;
}
/**
* Returns the visible client area that can be used for rendering.
* </p>
* @return the visible client area that can be used for rendering.
*/
protected abstract Rectangle getClientArea();
/**
* Return the font style that is currently set on the active
* gc. Font style cached for performance reasons.
*
* @return int SWT.BOLD, SWT.NORMAL
*/
protected int getCurrentFontStyle() {
return currentFontStyle;
}
/**
* Returns the <class>StyledTextContent</class> to use for line offset
* calculations.
* </p>
* @return the <class>StyledTextContent</class> to use for line offset
* calculations.
*/
protected abstract StyledTextContent getContent();
/**
* Returns the Device that is being rendered on.
* </p>
* @return the Device that is being rendered on.
*/
Device getDevice() {
return device;
}
/**
* Returns an array of text ranges that have a font style specified (e.g., SWT.BOLD).
* </p>
* @param styles style ranges in the line
* @param lineOffset start index of the line, relative to the start of the document
* @param length of the line
* @return StyleRange[], array of ranges with a font style specified,
* null if styles parameter is null
*/
private StyleRange[] getFontStyleRanges(StyleRange[] styles, int lineOffset, int lineLength) {
int count = 0;
StyleRange[] ranges = null;
if (styles == null) {
return null;
}
// figure out the number of ranges with font styles
for (int i = 0; i < styles.length; i++) {
StyleRange style = styles[i];
if (style.start - lineOffset < lineLength) {
if (style.fontStyle == SWT.BOLD) {
count++;
}
}
}
// get the style information
if (count > 0) {
ranges = new StyleRange[count];
count = 0;
for (int i = 0; i < styles.length; i++) {
StyleRange style = styles[i];
int styleLineStart = style.start - lineOffset;
if (styleLineStart < lineLength) {
if (style.fontStyle == SWT.BOLD) {
StyleRange newStyle = new StyleRange();
newStyle.start = Math.max(0, styleLineStart);
newStyle.length = (Math.min(styleLineStart + style.length, lineLength)) - newStyle.start;
ranges[count] = newStyle;
count++;
}
}
}
}
return ranges;
}
/**
* Returns the text segments that should be treated as if they
* had a different direction than the surrounding text.
* </p>
*
* @param lineOffset offset of the first character in the line.
* 0 based from the beginning of the document.
* @param line text of the line to specify bidi segments for
* @return text segments that should be treated as if they had a
* different direction than the surrounding text. Only the start
* index of a segment is specified, relative to the start of the
* line. Always starts with 0 and ends with the line length.
* @exception IllegalArgumentException <ul>
* <li>ERROR_INVALID_ARGUMENT - if the segment indices returned
* by the listener do not start with 0, are not in ascending order,
* exceed the line length or have duplicates</li>
* </ul>
*/
protected abstract int[] getBidiSegments(int lineOffset, String lineText);
/**
* Returns the GC to use for rendering and measuring.
* Allows subclasses to reuse GCs.
* </p>
* @return the GC to use for rendering and measuring.
*/
protected abstract GC getGC();
/**
* Returns the horizontal scroll position.
* </p>
* @return the horizontal scroll position.
*/
protected abstract int getHorizontalPixel();
/**
* Method getLeftMargin.
* @return int
*/
int getLeftMargin() {
return leftMargin;
}
/**
* Returns the width in pixels of the space used to represent line delimiters.
* @return the width in pixels of the space used to represent line delimiters.
*/
int getLineEndSpaceWidth() {
return lineEndSpaceWidth;
}
/**
* Returns the line background data for the given line or null if
* there is none.
* </p>
* @param lineOffset offset of the line start relative to the start
* of the content.
* @param line line to get line background data for
* @return line background data for the given line. may return null
*/
protected abstract StyledTextEvent getLineBackgroundData(int lineOffset, String line);
/**
* Returns the height in pixels of a line.
* </p>
* @return the height in pixels of a line.
*/
int getLineHeight() {
return lineHeight;
}
/**
* Returns the line style data for the specified line.
* The lineOffset and line may specify a segment of a logical line stored
* in the <class>StyledTextContent</class> of the widget.
* The returned styles are guaranteed to be at least partially on the
* segment.
* </p>
* @param event the styles for the logical line
* @param lineOffset offset of the line start relative to the start of
* the content.
* @param line line to get line styles for
* @return line style data for the given line segment. Styles may start
* before line start and end after line end but are guaranteed to be at
* least partially on the line.
*/
StyledTextEvent getLineStyleData(StyledTextEvent event, int lineOffset, String line) {
int lineLength = line.length();
if (event.styles != null && getWordWrap()) {
event.styles = getVisualLineStyleData(event.styles, lineOffset, lineLength);
}
if (event.styles == null) {
event.styles = new StyleRange[0];
}
else
if (isBidi()) {
GC gc = getGC();
if (StyledTextBidi.isLigated(gc)) {
// Check for ligatures that are partially styled, if one is found
// automatically apply the style to the entire ligature.
// Since ligatures can't extend over multiple lines (they aren't
// ligatures if they are separated by a line delimiter) we can ignore
// style starts or ends that are not on the current line.
// Note that there is no need to deal with segments when checking for
// the ligatures.
StyledTextBidi bidi = new StyledTextBidi(gc, line, new int[] {0, lineLength});
for (int i=0; i<event.styles.length; i++) {
StyleRange range = event.styles[i];
StyleRange newRange = null;
int relativeStart = range.start - lineOffset;
if (relativeStart >= 0) {
int startLigature = bidi.getLigatureStartOffset(relativeStart);
if (startLigature != relativeStart) {
newRange = (StyleRange) range.clone();
range = event.styles[i] = newRange;
range.start = range.start - (relativeStart - startLigature);
range.length = range.length + (relativeStart - startLigature);
}
}
int rangeEnd = range.start + range.length;
int relativeEnd = rangeEnd - lineOffset - 1;
if (relativeEnd < lineLength) {
int endLigature = bidi.getLigatureEndOffset(relativeEnd);
if (endLigature != relativeEnd) {
if (newRange == null) {
newRange = (StyleRange) range.clone();
range = event.styles[i] = newRange;
}
range.length = range.length + (endLigature - relativeEnd);
}
}
}
}
disposeGC(gc);
}
return event;
}
/**
* Returns the line style data for the given line or null if there is
* none. If there is a LineStyleListener but it does not set any styles,
* the StyledTextEvent.styles field will be initialized to an empty
* array.
* </p>
*
* @param lineOffset offset of the line start relative to the start of
* the content.
* @param line line to get line styles for
* @return line style data for the given line. Styles may start before
* line start and end after line end
*/
protected abstract StyledTextEvent getLineStyleData(int lineOffset, String line);
/**
* Returns the widget selection.
* Implemented by subclasses for optional selection rendering.
* </p>
* @return the widget selection.
*/
protected abstract Point getSelection();
/**
* Merges the selection into the styles that are passed in.
* The font style of existing style ranges is preserved in the selection.
* Implemented by subclasses for optional selection rendering.
* </p>
* @param styles the existing styles that the selection should be
* applied to.
* @return the selection style range merged with the existing styles
*/
protected abstract StyleRange[] mergeSelectionLineStyles(StyleRange[] styles);
/**
* Returns a StyledTextBidi object for the specified line.
* </p>
*
* @param lineText the line that the StyledTextBidi object should
* work on.
* @param lineOffset offset of the beginning of the line, relative
* to the beginning of the document
* @param gc GC to use when creating a new StyledTextBidi object.
* @param styles StyleRanges to use when creating a new StyledTextBidi
* object.
* @return a StyledTextBidi object for the specified line.
*/
StyledTextBidi getStyledTextBidi(String lineText, int lineOffset, GC gc, StyleRange[] styles) {
StyleRange[] fontStyles = null;
if (styles == null) {
StyledTextEvent event = getLineStyleData(lineOffset, lineText);
if (event != null) {
fontStyles = getFontStyleRanges(event.styles, lineOffset, lineText.length());
}
}
else {
fontStyles = getFontStyleRanges(styles, lineOffset, lineText.length());
}
return new StyledTextBidi(gc, tabWidth, lineText, fontStyles, boldFont, getBidiSegments(lineOffset, lineText));
}
/**
* Returns the width of the specified text segment.
* Expands tabs to tab stops using the widget tab width.
* </p>
*
* @param text text to measure
* @param textStartOffset offset of the first character in text relative
* to the first character in the document
* @param lineStyles styles of the line
* @param paintX x location to start drawing at
* @param gc GC to measure with
* @return the width of the specified text segment.
*/
protected abstract int getStyledTextWidth(String text, int textStartOffset, StyleRange[] lineStyles, int paintX, GC gc);
/**
* Returns the next tab stop for the specified x location.
* </p>
*
* @param x the x location in front of a tab
* @return the next tab stop for the specified x location.
*/
private int getTabStop(int x) {
int spaceWidth = tabWidth / tabLength;
// make sure tab stop is at least one space width apart
// from the last character. fixes 4844.
if (tabWidth - x % tabWidth < spaceWidth) {
x += tabWidth;
}
x += tabWidth;
x -= x % tabWidth;
return x;
}
/**
* Returns the x position of the character at the specified offset
* relative to the first character in the line.
* Expands tabs to tab stops using the widget tab width.
* </p>
*
* @param text text to be measured.
* @param lineOffset offset of the first character in the line.
* @param length number of characters to measure. Tabs are counted
* as one character in this parameter.
* @param styles line styles
* @param gc GC to use for measuring text
* @return x position of the character at the specified offset with tabs
* expanded to tab stops. 0 if the length is outside the specified text.
*/
int getTextPosition(String text, int lineOffset, int length, StyleRange[] lineStyles, GC gc) {
return getTextWidth(text, lineOffset, 0, length, lineStyles, 0, gc);
}
/**
* Returns the width of the specified text range. Expand tabs to tab stops using
* the widget tab width.
* </p>
*
* @param text text to be measured.
* @param lineOffset offset of the first character in the line.
* @param startOffset offset of the character to start measuring and
* expand tabs.
* @param length number of characters to measure. Tabs are counted
* as one character in this parameter.
* @param styles line styles
* @param startXOffset x position of "startOffset" in "text". Used for
* calculating tab stops
* @param gc GC to use for measuring text
* @return width of the text range with tabs expanded to tab stops or 0 if the
* startOffset or length is outside the specified text.
*/
int getTextWidth(String text, int lineOffset, int startOffset, int length, StyleRange[] lineStyles, int startXOffset, GC gc) {
int paintX = 0;
int endOffset = startOffset + length;
int textLength = text.length();
if (startOffset < 0 || startOffset >= textLength || endOffset > textLength) {
return paintX;
}
for (int i = startOffset; i < endOffset; i++) {
int tabIndex = text.indexOf(StyledText.TAB, i);
// is tab not present or past the rendering range?
if (tabIndex == -1 || tabIndex > endOffset) {
tabIndex = endOffset;
}
if (tabIndex != i) {
String tabSegment = text.substring(i, tabIndex);
if (lineStyles != null) {
paintX = getStyledTextWidth(tabSegment, lineOffset + i, lineStyles, paintX, gc);
}
else {
setLineFont(gc, SWT.NORMAL);
paintX += gc.stringExtent(tabSegment).x;
}
if (tabIndex != endOffset && tabWidth > 0) {
paintX = getTabStop(startXOffset + paintX) - startXOffset;
}
i = tabIndex;
}
else
if (tabWidth > 0) {
paintX = getTabStop(startXOffset + paintX) - startXOffset;
}
}
return paintX;
}
/**
* Returns styles for the specified visual (wrapped) line.
* </p>
*
* @param logicalStyles the styles for a logical (unwrapped) line
* @param lineOffset offset of the visual line
* @param lineLength length of the visual line
* @return styles in the logicalStyles array that are at least
* partially on the specified visual line.
*/
StyleRange[] getVisualLineStyleData(StyleRange[] logicalStyles, int lineOffset, int lineLength) {
int lineEnd = lineOffset + lineLength;
int oldStyleCount = logicalStyles.length;
int newStyleCount = 0;
for (int i = 0; i < oldStyleCount; i++) {
StyleRange style = logicalStyles[i];
if (style.start < lineEnd && style.start + style.length > lineOffset) {
newStyleCount++;
}
}
if (newStyleCount != oldStyleCount) {
StyleRange[] newStyles = new StyleRange[newStyleCount];
for (int i = 0, j = 0; i < oldStyleCount; i++) {
StyleRange style = logicalStyles[i];
if (style.start < lineEnd && style.start + style.length > lineOffset) {
newStyles[j++] = logicalStyles[i];
}
}
logicalStyles = newStyles;
}
return logicalStyles;
}
/**
* Returns the word wrap state.
* </p>
* @return true=word wrap is on. false=no word wrap, lines may extend
* beyond the right side of the client area.
*/
protected abstract boolean getWordWrap();
/**
* Returns whether the widget is running on a bidi platform.
* </p>
* @return true=the widget is running on a bidi platform, false=otherwise.
*/
boolean isBidi() {
return isBidi;
}
/**
* Returns whether the widget was created with the SWT.FULL_SELECTION style.
* Implemented by subclasses for optional selection rendering.
* </p>
* @return true=the widget is running in full line selection mode,
* false=otherwise
*/
protected abstract boolean isFullLineSelection();
/**
* Set the font style that is set for the active
* gc. Font style cached for performance reasons.
*
* @param style SWT.BOLD, SWT.NORMAL
*/
protected void setCurrentFontStyle(int style) {
currentFontStyle = style;
}
/**
* Sets the background of the specified GC for a line rendering operation,
* if it is not already set.
* </p>
*
* @param gc GC to set the background color in
* @param currentBackground background color currently set in gc
* @param newBackground new background color of gc
*/
private Color setLineBackground(GC gc, Color currentBackground, Color newBackground) {
if (currentBackground.equals(newBackground) == false) {
gc.setBackground(newBackground);
}
return newBackground;
}
/**
* Sets the font of the specified GC if it is not already set.
* </p>
*
* @param gc GC to set the font in
* @param style desired style of the font in gc. Can be one of SWT.NORMAL, SWT.
* BOLD
*/
void setLineFont(GC gc, int style) {
if (getCurrentFontStyle() != style) {
setCurrentFontStyle(style);
if (style == SWT.BOLD) {
gc.setFont(boldFont);
}
else
if (style == SWT.NORMAL) {
gc.setFont(regularFont);
}
}
}
/**
* Sets the foreground of the specified GC for a line rendering operation,
* if it is not already set.
* </p>
*
* @param gc GC to set the foreground color in
* @param currentForeground foreground color currently set in gc
* @param newForeground new foreground color of gc
*/
private Color setLineForeground(GC gc, Color currentForeground, Color newForeground) {
if (currentForeground.equals(newForeground) == false) {
gc.setForeground(newForeground);
}
return newForeground;
}
/**
* Calculates the width in pixel of a tab character
* </p>
* @param tabLength number of space characters represented by a tab character.
*/
void setTabLength(int tabLength) {
GC gc = getGC();
StringBuffer tabBuffer = new StringBuffer(tabLength);
this.tabLength = tabLength;
for (int i = 0; i < tabLength; i++) {
tabBuffer.append(' ');
}
tabWidth = gc.stringExtent(tabBuffer.toString()).x;
disposeGC(gc);
}
}