/***************************************************************************** * Copyright (c) 2015 CEA LIST. * * 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: * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation * *****************************************************************************/ package org.eclipse.nebula.widgets.richtext.painter.instructions; import java.util.ArrayList; import java.util.List; import org.eclipse.nebula.widgets.richtext.painter.LinePainter; import org.eclipse.nebula.widgets.richtext.painter.TagProcessingState; import org.eclipse.nebula.widgets.richtext.painter.TagProcessingState.TextAlignment; import org.eclipse.swt.graphics.FontMetrics; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; /** * {@link PaintInstruction} to paint text based on the current {@link TagProcessingState}. */ public class TextPaintInstruction implements PaintInstruction { private TagProcessingState state; private String text; private List<String> words = new ArrayList<>(); public TextPaintInstruction(TagProcessingState state, String text) { this.state = state; this.text = text; // extract and store the trimmed words in the text String word = text.trim(); if (word.length() > 0) { String[] splitText = word.split("\\s"); for (String splitWord : splitText) { String trimmed = splitWord.trim(); if (trimmed.length() > 0) { words.add(trimmed); } } } } @Override public void paint(GC gc, Rectangle area) { if (!this.state.isRendering()) { return; } FontMetrics metrics = gc.getFontMetrics(); FontMetrics metricsToUse = metrics; int baseline = metrics.getAscent() + metrics.getLeading(); int yAdvance = 0; if (this.state.getCurrentLineHeight() > metrics.getHeight()) { int biggerBaseline = this.state.getCurrentBiggestFontMetrics().getAscent() + this.state.getCurrentBiggestFontMetrics().getLeading(); yAdvance = biggerBaseline - baseline; metricsToUse = this.state.getCurrentBiggestFontMetrics(); } Point pointer = this.state.getPointer(); // on alignment justify render word by word int textLength = 0; if (TextAlignment.JUSTIFY.equals(this.state.getTextAlignment())) { LinePainter line = this.state.getCurrentLine(); for (String word : this.words) { gc.drawText(word, pointer.x, pointer.y + yAdvance, (!this.state.hasPreviousBgColor())); int length = gc.textExtent(word).x + line.getNextJustifySpace(); pointer.x += length; textLength += length; } } else { textLength = getTextLength(gc); gc.drawText(text, pointer.x, pointer.y + yAdvance, (!this.state.hasPreviousBgColor())); } if (this.state.isUnderlineActive()) { int underlineY = pointer.y + baseline + yAdvance + (metricsToUse.getDescent() / 2); gc.drawLine(pointer.x, underlineY, pointer.x + textLength, underlineY); } if (this.state.isStrikethroughActive()) { int strikeY = pointer.y + yAdvance + (metrics.getHeight() / 2) + (metrics.getLeading() / 2); gc.drawLine(pointer.x, strikeY, pointer.x + textLength, strikeY); } if (!TextAlignment.JUSTIFY.equals(this.state.getTextAlignment())) { pointer.x += textLength; } } public int getTextLength(GC gc) { // TODO caching of textExtent return gc.textExtent(text).x; } public int getTrimmedTextLength(GC gc) { int result = 0; for (String word : this.words) { // TODO caching of textExtent result += gc.textExtent(word).x; } return result; } public String getText() { return this.text; } public List<String> getWords() { return this.words; } }