/******************************************************************************* | |
* 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.update.ui.forms.internal.engine; | |
import org.eclipse.swt.graphics.*; | |
import org.eclipse.jface.resource.JFaceResources; | |
import java.util.Hashtable; | |
import org.eclipse.swt.SWT; | |
import java.text.BreakIterator; | |
import java.util.Vector; | |
/** | |
* @version 1.0 | |
* @author | |
*/ | |
public class TextSegment extends ParagraphSegment implements ITextSegment { | |
private Color color; | |
private String fontId; | |
private String text; | |
protected boolean underline; | |
private boolean wrapAllowed = true; | |
protected Vector areaRectangles = new Vector(); | |
class AreaRectangle { | |
Rectangle rect; | |
int from, to; | |
public AreaRectangle(Rectangle rect, int from, int to) { | |
this.rect = rect; | |
this.from = from; | |
this.to = to; | |
} | |
public boolean contains(int x, int y) { | |
return rect.contains(x, y); | |
} | |
public String getText() { | |
if (from==0 && to== -1) | |
return TextSegment.this.getText(); | |
if (from >0 && to == -1) | |
return TextSegment.this.getText().substring(from); | |
return TextSegment.this.getText().substring(from, to); | |
} | |
} | |
public TextSegment(String text, String fontId) { | |
this.text = cleanup(text); | |
this.fontId = fontId; | |
} | |
private String cleanup(String text) { | |
StringBuffer buf = new StringBuffer(); | |
for (int i = 0; i < text.length(); i++) { | |
char c = text.charAt(i); | |
if (c == '\n' || c == '\r' || c=='\f') { | |
if (i > 0) | |
buf.append(' '); | |
} else | |
buf.append(c); | |
} | |
return buf.toString(); | |
} | |
public void setWordWrapAllowed(boolean value) { | |
wrapAllowed = value; | |
} | |
public boolean isWordWrapAllowed() { | |
return wrapAllowed; | |
} | |
public boolean isSelectable() { | |
return false; | |
} | |
public Color getColor() { | |
return color; | |
} | |
public Font getFont() { | |
if (fontId == null) | |
return JFaceResources.getDefaultFont(); | |
else | |
return JFaceResources.getFontRegistry().get(fontId); | |
} | |
public String getText() { | |
return text; | |
} | |
void setText(String text) { | |
this.text = cleanup(text); | |
} | |
void setColor(Color color) { | |
this.color = color; | |
} | |
void setFontId(String fontId) { | |
this.fontId = fontId; | |
} | |
public boolean contains(int x, int y) { | |
for (int i = 0; i < areaRectangles.size(); i++) { | |
AreaRectangle ar = (AreaRectangle) areaRectangles.get(i); | |
if (ar.contains(x, y)) | |
return true; | |
} | |
return false; | |
} | |
public Rectangle getBounds() { | |
int x=0, y=0; | |
int width = 0, height = 0; | |
for (int i=0; i<areaRectangles.size(); i++) { | |
AreaRectangle ar = (AreaRectangle)areaRectangles.get(i); | |
if (i==0) y = ar.rect.y; | |
x = Math.min(ar.rect.x, x); | |
width = Math.max(ar.rect.width, width); | |
height += ar.rect.height; | |
} | |
return new Rectangle(x, y, width, height); | |
} | |
public void advanceLocator( | |
GC gc, | |
int wHint, | |
Locator locator, | |
Hashtable objectTable) { | |
Font oldFont = null; | |
if (fontId != null) { | |
oldFont = gc.getFont(); | |
gc.setFont(getFont()); | |
} | |
FontMetrics fm = gc.getFontMetrics(); | |
int lineHeight = fm.getHeight(); | |
if (wHint == SWT.DEFAULT || !wrapAllowed) { | |
Point extent = gc.textExtent(text); | |
if (locator.x + extent.x > wHint) { | |
// new line | |
locator.x = isSelectable()?locator.indent+1:locator.indent; | |
locator.y += locator.rowHeight; | |
locator.rowHeight = 0; | |
} | |
int width = extent.x; | |
if (isSelectable()) width+=2; | |
locator.x += width; | |
locator.width = width; | |
locator.height = extent.y; | |
locator.rowHeight = Math.max(locator.rowHeight, extent.y); | |
return; | |
} | |
BreakIterator wb = BreakIterator.getLineInstance(); | |
wb.setText(text); | |
int saved = 0; | |
int last = 0; | |
int width = 0; | |
Point lastExtent = null; | |
for (int loc = wb.first(); loc != BreakIterator.DONE; loc = wb.next()) { | |
String word = text.substring(saved, loc); | |
Point extent = gc.textExtent(word); | |
if (locator.x + extent.x > wHint) { | |
// overflow | |
String savedWord = text.substring(saved, last); | |
if (lastExtent==null) | |
lastExtent = gc.textExtent(savedWord); | |
int lineWidth = locator.x + lastExtent.x; | |
if (isSelectable()) lineWidth+=2; | |
saved = last; | |
locator.rowHeight = Math.max(locator.rowHeight, lastExtent.y); | |
locator.x = isSelectable()?locator.indent+1:locator.indent; | |
locator.y += locator.rowHeight; | |
locator.rowHeight = 0; | |
width = Math.max(width, lineWidth); | |
} | |
last = loc; | |
lastExtent = extent; | |
} | |
String lastString = text.substring(saved, last); | |
Point extent = gc.textExtent(lastString); | |
int lineWidth = extent.x; | |
if (isSelectable()) lineWidth += 2; | |
locator.x += lineWidth; | |
locator.width = width; | |
locator.height = lineHeight; | |
locator.rowHeight = Math.max(locator.rowHeight, extent.y); | |
if (oldFont != null) { | |
gc.setFont(oldFont); | |
} | |
} | |
public void paint( | |
GC gc, | |
int width, | |
Locator locator, | |
Hashtable objectTable, | |
boolean selected) { | |
Font oldFont = null; | |
Color oldColor = null; | |
areaRectangles.clear(); | |
if (fontId != null) { | |
oldFont = gc.getFont(); | |
gc.setFont(getFont()); | |
} | |
if (color != null) { | |
oldColor = gc.getForeground(); | |
gc.setForeground(color); | |
} | |
FontMetrics fm = gc.getFontMetrics(); | |
int lineHeight = fm.getHeight(); | |
int descent = fm.getDescent(); | |
if (!wrapAllowed) { | |
Point extent = gc.textExtent(text); | |
int ewidth = extent.x; | |
if (isSelectable()) ewidth += 2; | |
if (locator.x + ewidth > width) { | |
// new line | |
locator.resetCaret(); | |
if (isSelectable()) locator.x += 1; | |
locator.y += locator.rowHeight; | |
locator.rowHeight = 0; | |
} | |
gc.drawString(text, locator.x, locator.y); | |
if (underline) { | |
int lineY = locator.y + lineHeight - descent + 1; | |
gc.drawLine(locator.x, lineY, locator.x + extent.x, lineY); | |
} | |
Rectangle br = | |
new Rectangle(locator.x - 1, locator.y, extent.x + 2, lineHeight - descent + 3); | |
areaRectangles.add(new AreaRectangle(br, 0, -1)); | |
if (selected) { | |
if (color != null) | |
gc.setForeground(oldColor); | |
gc.drawFocus(br.x, br.y, br.width, br.height); | |
} | |
locator.x += ewidth; | |
locator.width = ewidth; | |
locator.height = lineHeight; | |
locator.rowHeight = Math.max(locator.rowHeight, extent.y); | |
if (oldFont != null) { | |
gc.setFont(oldFont); | |
} | |
if (oldColor != null) { | |
gc.setForeground(oldColor); | |
} | |
return; | |
} | |
BreakIterator wb = BreakIterator.getLineInstance(); | |
wb.setText(text); | |
int saved = 0; | |
int last = 0; | |
for (int loc = wb.first(); loc != BreakIterator.DONE; loc = wb.next()) { | |
if (loc == 0) | |
continue; | |
String word = text.substring(saved, loc); | |
Point extent = gc.textExtent(word); | |
int ewidth = extent.x; | |
if (isSelectable()) ewidth += 2; | |
if (locator.x + ewidth > width) { | |
// overflow | |
String prevLine = text.substring(saved, last); | |
gc.drawString(prevLine, locator.x, locator.y, true); | |
Point prevExtent = gc.textExtent(prevLine); | |
int prevWidth = prevExtent.x; | |
if (isSelectable()) prevWidth += 2; | |
if (underline) { | |
int lineY = locator.y + lineHeight - descent + 1; | |
gc.drawLine(locator.x, lineY, locator.x + prevWidth, lineY); | |
} | |
Rectangle br = | |
new Rectangle( | |
locator.x - 1, | |
locator.y, | |
prevExtent.x + 2, | |
lineHeight - descent + 3); | |
if (selected) { | |
if (color != null) | |
gc.setForeground(oldColor); | |
gc.drawFocus(br.x, br.y, br.width, br.height); | |
if (color != null) | |
gc.setForeground(color); | |
} | |
areaRectangles.add(new AreaRectangle(br, saved, last)); | |
locator.rowHeight = Math.max(locator.rowHeight, prevExtent.y); | |
locator.resetCaret(); | |
if (isSelectable()) locator.x +=1; | |
locator.y += locator.rowHeight; | |
locator.rowHeight = 0; | |
saved = last; | |
} | |
last = loc; | |
} | |
// paint the last line | |
String lastLine = text.substring(saved, last); | |
gc.drawString(lastLine, locator.x, locator.y, true); | |
Point lastExtent = gc.textExtent(lastLine); | |
int lastWidth = lastExtent.x; | |
if (isSelectable()) lastWidth += 2; | |
Rectangle br = | |
new Rectangle( | |
locator.x - 1, | |
locator.y, | |
lastExtent.x + 2, | |
lineHeight - descent + 3); | |
areaRectangles.add(new AreaRectangle(br, saved, last)); | |
if (underline) { | |
int lineY = locator.y + lineHeight - descent + 1; | |
gc.drawLine(locator.x, lineY, locator.x + lastExtent.x, lineY); | |
} | |
if (selected) { | |
if (color != null) | |
gc.setForeground(oldColor); | |
gc.drawFocus(br.x, br.y, br.width, br.height); | |
} | |
locator.x += lastWidth; | |
locator.rowHeight = Math.max(locator.rowHeight, lastExtent.y); | |
if (oldFont != null) { | |
gc.setFont(oldFont); | |
} | |
if (oldColor != null) { | |
gc.setForeground(oldColor); | |
} | |
} | |
public void paintFocus(GC gc, Color bg, Color fg, boolean selected) { | |
if (areaRectangles==null) return; | |
for (int i=0; i<areaRectangles.size(); i++) { | |
AreaRectangle areaRectangle = (AreaRectangle)areaRectangles.get(i); | |
Rectangle br = areaRectangle.rect; | |
if (selected) { | |
gc.setBackground(bg); | |
gc.setForeground(fg); | |
gc.drawFocus(br.x, br.y, br.width, br.height); | |
} | |
else { | |
gc.setForeground(bg); | |
gc.drawRectangle(br.x, br.y, br.width-1, br.height-1); | |
} | |
} | |
} | |
} |