blob: 0ec9682e68f6d2b7e0b0df485eff452980c4ae09 [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.update.ui.forms.internal.engine;
import java.io.*;
import java.util.*;
import javax.xml.parsers.*;
import org.eclipse.core.runtime.*;
import org.eclipse.jface.resource.*;
import org.eclipse.update.ui.forms.internal.*;
import org.w3c.dom.*;
import org.xml.sax.*;
/**
* @version 1.0
* @author
*/
public class TextModel implements ITextModel {
private static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
Vector paragraphs;
IHyperlinkListener urlListener;
IHyperlinkSegment[] hyperlinks;
int selectedLinkIndex = -1;
HyperlinkSettings hyperlinkSettings;
public TextModel() {
reset();
}
class LocalHyperlinkSettings extends HyperlinkSettings {
}
/*
* @see ITextModel#getParagraphs()
*/
public IParagraph[] getParagraphs() {
if (paragraphs == null)
return new IParagraph[0];
return (IParagraph[]) paragraphs.toArray(
new IParagraph[paragraphs.size()]);
}
public String getAccessibleText() {
if (paragraphs == null)
return "";
StringBuffer sbuf = new StringBuffer();
for (int i=0; i<paragraphs.size(); i++) {
IParagraph paragraph = (IParagraph)paragraphs.get(i);
String text = paragraph.getAccessibleText();
sbuf.append(text);
}
return sbuf.toString();
}
/*
* @see ITextModel#parse(String)
*/
public void parseTaggedText(String taggedText, boolean expandURLs)
throws CoreException {
if (taggedText==null) {
reset();
return;
}
try {
InputStream stream =
new ByteArrayInputStream(taggedText.getBytes("UTF8"));
parseInputStream(stream, expandURLs);
} catch (UnsupportedEncodingException e) {
}
}
public void parseInputStream(InputStream is, boolean expandURLs)
throws CoreException {
documentBuilderFactory.setNamespaceAware(true);
reset();
try {
DocumentBuilder parser = documentBuilderFactory.newDocumentBuilder();
InputSource source = new InputSource(is);
Document doc = parser.parse(source);
processDocument(doc, expandURLs);
} catch (ParserConfigurationException e) {
FormsPlugin.logException(e);
} catch (SAXException e) {
FormsPlugin.logException(e);
} catch (IOException e) {
FormsPlugin.logException(e);
}
}
private void processDocument(Document doc, boolean expandURLs) {
Node root = doc.getDocumentElement();
NodeList children = root.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeType() == Node.TEXT_NODE) {
// Make an implicit paragraph
String text = child.getNodeValue();
if (text != null && !isIgnorableWhiteSpace(text, true)) {
Paragraph p = new Paragraph(true);
p.parseRegularText(
text,
expandURLs,
getHyperlinkSettings(),
null);
paragraphs.add(p);
}
} else if (child.getNodeType() == Node.ELEMENT_NODE) {
String tag = child.getNodeName().toLowerCase();
if (tag.equals("p")) {
IParagraph p = processParagraph(child, expandURLs);
if (p != null)
paragraphs.add(p);
} else if (tag.equals("li")) {
IParagraph p = processListItem(child, expandURLs);
if (p != null)
paragraphs.add(p);
}
}
}
}
private IParagraph processParagraph(Node paragraph, boolean expandURLs) {
NodeList children = paragraph.getChildNodes();
NamedNodeMap atts = paragraph.getAttributes();
Node addSpaceAtt = atts.getNamedItem("addVerticalSpace");
boolean addSpace = true;
if (addSpaceAtt != null) {
String value = addSpaceAtt.getNodeValue();
addSpace = value.equalsIgnoreCase("true");
}
Paragraph p = new Paragraph(addSpace);
processSegments(p, children, expandURLs);
return p;
}
private IParagraph processListItem(Node listItem, boolean expandURLs) {
NodeList children = listItem.getChildNodes();
NamedNodeMap atts = listItem.getAttributes();
Node addSpaceAtt = atts.getNamedItem("addVerticalSpace");
Node styleAtt = atts.getNamedItem("style");
Node valueAtt = atts.getNamedItem("value");
Node indentAtt = atts.getNamedItem("indent");
int style = IBulletParagraph.CIRCLE;
int indent = -1;
String text = null;
boolean addSpace = true;
if (addSpaceAtt != null) {
String value = addSpaceAtt.getNodeValue();
addSpace = value.equalsIgnoreCase("true");
}
if (styleAtt != null) {
String value = styleAtt.getNodeValue();
if (value.equalsIgnoreCase("text")) {
style = IBulletParagraph.TEXT;
} else if (value.equalsIgnoreCase("image")) {
style = IBulletParagraph.IMAGE;
}
}
if (valueAtt != null) {
text = valueAtt.getNodeValue();
}
if (indentAtt != null) {
String value = indentAtt.getNodeValue();
try {
indent = Integer.parseInt(value);
} catch (NumberFormatException e) {
}
}
BulletParagraph p = new BulletParagraph(addSpace);
p.setIndent(indent);
p.setBulletStyle(style);
p.setBulletText(text);
processSegments(p, children, expandURLs);
return p;
}
private void processSegments(
Paragraph p,
NodeList children,
boolean expandURLs) {
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
IParagraphSegment segment = null;
if (child.getNodeType() == Node.TEXT_NODE) {
String value = child.getNodeValue();
if (value != null && !isIgnorableWhiteSpace(value, false)) {
p.parseRegularText(
value,
expandURLs,
getHyperlinkSettings(),
null);
}
} else if (child.getNodeType() == Node.ELEMENT_NODE) {
String name = child.getNodeName();
if (name.equalsIgnoreCase("img")) {
segment = processImageSegment(child);
} else if (name.equalsIgnoreCase("a")) {
segment =
processHyperlinkSegment(child, getHyperlinkSettings());
} else if (name.equalsIgnoreCase("text")) {
processTextSegment(p, expandURLs, child);
} else if (name.equalsIgnoreCase("b")) {
String text = getNodeText(child).trim();
String fontId = JFaceResources.BANNER_FONT;
p.parseRegularText(
text,
expandURLs,
getHyperlinkSettings(),
fontId);
}
}
if (segment != null) {
p.addSegment(segment);
}
}
}
private boolean isIgnorableWhiteSpace(String text, boolean ignoreSpaces) {
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (ignoreSpaces && c == ' ')
continue;
if (c == '\n' || c == '\r' || c == '\f')
continue;
return false;
}
return true;
}
private IParagraphSegment processImageSegment(Node image) {
ImageSegment segment = new ImageSegment();
NamedNodeMap atts = image.getAttributes();
Node id = atts.getNamedItem("href");
Node align = atts.getNamedItem("align");
if (id != null) {
String value = id.getNodeValue();
segment.setObjectId(value);
}
if (align != null) {
String value = align.getNodeValue().toLowerCase();
if (value.equals("top"))
segment.setVerticalAlignment(ImageSegment.TOP);
else if (value.equals("middle"))
segment.setVerticalAlignment(ImageSegment.MIDDLE);
else if (value.equals("bottom"))
segment.setVerticalAlignment(ImageSegment.BOTTOM);
}
return segment;
}
private String getNodeText(Node node) {
NodeList children = node.getChildNodes();
String text = "";
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeType() == Node.TEXT_NODE) {
text += child.getNodeValue();
}
}
return text;
}
private IParagraphSegment processHyperlinkSegment(
Node link,
HyperlinkSettings settings) {
String text = getNodeText(link);
HyperlinkSegment segment = new HyperlinkSegment(text, settings, null);
NamedNodeMap atts = link.getAttributes();
Node href = atts.getNamedItem("href");
if (href != null) {
String value = href.getNodeValue();
segment.setActionId(value);
}
Node arg = atts.getNamedItem("arg");
if (arg != null) {
String value = arg.getNodeValue();
segment.setArg(value);
}
return segment;
}
private void processTextSegment(
Paragraph p,
boolean expandURLs,
Node textNode) {
String text = getNodeText(textNode).trim();
NamedNodeMap atts = textNode.getAttributes();
Node font = atts.getNamedItem("font");
String fontId = null;
if (font != null) {
fontId = font.getNodeValue();
}
p.parseRegularText(text, expandURLs, getHyperlinkSettings(), fontId);
}
public void parseRegularText(String regularText, boolean convertURLs)
throws CoreException {
reset();
if (regularText==null) return;
Paragraph p = new Paragraph(true);
paragraphs.add(p);
int pstart = 0;
for (int i = 0; i < regularText.length(); i++) {
char c = regularText.charAt(i);
if (p == null) {
p = new Paragraph(true);
paragraphs.add(p);
}
if (c == '\n') {
String text = regularText.substring(pstart, i);
pstart = i + 1;
p.parseRegularText(
text,
convertURLs,
getHyperlinkSettings(),
null);
p = null;
}
}
if (p != null) {
// no new line
String text = regularText.substring(pstart);
p.parseRegularText(text, convertURLs, getHyperlinkSettings(), null);
}
}
public HyperlinkSettings getHyperlinkSettings() {
if (hyperlinkSettings == null) {
hyperlinkSettings = new LocalHyperlinkSettings();
}
return hyperlinkSettings;
}
public void setHyperlinkSettings(HyperlinkSettings settings) {
this.hyperlinkSettings = settings;
}
public void setURLListener(IHyperlinkListener urlListener) {
this.urlListener = urlListener;
}
private void reset() {
if (paragraphs == null)
paragraphs = new Vector();
paragraphs.clear();
selectedLinkIndex = -1;
hyperlinks = null;
}
IHyperlinkSegment[] getHyperlinks() {
if (hyperlinks != null || paragraphs == null)
return hyperlinks;
Vector result = new Vector();
for (int i = 0; i < paragraphs.size(); i++) {
IParagraph p = (IParagraph) paragraphs.get(i);
IParagraphSegment[] segments = p.getSegments();
for (int j = 0; j < segments.length; j++) {
if (segments[j] instanceof IHyperlinkSegment)
result.add(segments[j]);
}
}
hyperlinks =
(IHyperlinkSegment[]) result.toArray(
new IHyperlinkSegment[result.size()]);
return hyperlinks;
}
public IHyperlinkSegment findHyperlinkAt(int x, int y) {
IHyperlinkSegment[] links = getHyperlinks();
for (int i = 0; i < links.length; i++) {
if (links[i].contains(x, y))
return links[i];
}
return null;
}
public ITextSegment findSegmentAt(int x, int y) {
for (int i = 0; i < paragraphs.size(); i++) {
IParagraph p = (IParagraph) paragraphs.get(i);
ITextSegment segment = p.findSegmentAt(x, y);
if (segment != null)
return segment;
}
return null;
}
public IHyperlinkSegment getSelectedLink() {
if (selectedLinkIndex == -1)
return null;
return hyperlinks[selectedLinkIndex];
}
public boolean traverseLinks(boolean next) {
IHyperlinkSegment[] links = getHyperlinks();
if (links == null)
return false;
int size = links.length;
if (next) {
selectedLinkIndex++;
} else
selectedLinkIndex--;
if (selectedLinkIndex < 0 || selectedLinkIndex > size - 1) {
selectedLinkIndex = -1;
}
return selectedLinkIndex != -1;
}
public void selectLink(IHyperlinkSegment link) {
if (link == null)
selectedLinkIndex = -1;
else {
IHyperlinkSegment[] links = getHyperlinks();
selectedLinkIndex = -1;
if (links == null)
return;
for (int i = 0; i < links.length; i++) {
if (links[i].equals(link)) {
selectedLinkIndex = i;
break;
}
}
}
}
public boolean hasFocusSegments() {
IHyperlinkSegment[] links = getHyperlinks();
if (links.length > 0)
return true;
return false;
}
public void dispose() {
if (hyperlinkSettings instanceof LocalHyperlinkSettings)
hyperlinkSettings.dispose();
}
}