introduce CSS function image(); parse content CSS property in own class
Signed-off-by: Florian Thienel <florian@thienel.org>
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/BatikBehaviorTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/BatikBehaviorTest.java
index 8760d40..4737763 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/BatikBehaviorTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/BatikBehaviorTest.java
@@ -50,7 +50,7 @@
final Element element = new Element("plan");
final IElement before = styleSheet.getPseudoElementBefore(element);
final Styles beforeStyles = styleSheet.getStyles(before);
- assertEquals("test", beforeStyles.getTextualContent(element).get(0));
+ assertEquals("test", beforeStyles.getTextualContent());
assertEquals(123.0f, beforeStyles.getFontSize(), 0.0f);
}
@@ -63,7 +63,7 @@
assertEquals(123.0f, styles.getFontSize(), 0.0f);
final IElement before = styleSheet.getPseudoElementBefore(element);
final Styles beforeStyles = styleSheet.getStyles(before);
- assertEquals("test", beforeStyles.getTextualContent(element).get(0));
+ assertEquals("test", beforeStyles.getTextualContent());
assertEquals(123.0f, beforeStyles.getFontSize(), 0.0f);
}
@@ -76,9 +76,8 @@
final Element nochild = new Element("child");
child.setParent(element);
final Styles styles = styleSheet.getStyles(child);
- assertEquals(1, styles.getTextualContent(element).size());
- assertEquals("child", styles.getTextualContent(element).get(0));
+ assertEquals("child", styles.getTextualContent());
final Styles nochildStyles = styleSheet.getStyles(nochild);
- assertEquals("nochild", nochildStyles.getTextualContent(element).get(0));
+ assertEquals("nochild", nochildStyles.getTextualContent());
}
}
\ No newline at end of file
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/CssTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/CssTest.java
index a770e76..00f97b0 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/CssTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/CssTest.java
@@ -579,9 +579,9 @@
final Styles styles = ss.getStyles(element);
- assertEquals("Before", styles.getTextualContent(element).get(0));
+ assertEquals("Before", styles.getTextualContent());
element.setAttribute("attribute", "After");
- assertEquals("After", styles.getTextualContent(element).get(0));
+ assertEquals("After", styles.getTextualContent());
}
@Test
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/MockLU.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/MockLU.java
index 3fe3306..477ed0e 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/MockLU.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/MockLU.java
@@ -21,32 +21,57 @@
lexicalUnitType = type;
}
- public static LexicalUnit INHERIT = new MockLU(LexicalUnit.SAC_INHERIT);
+ public static final MockLU INHERIT = new MockLU(LexicalUnit.SAC_INHERIT);
- public static LexicalUnit createFloat(final short units, final float value) {
+ public static MockLU createFloat(final short units, final float value) {
final MockLU lu = new MockLU(units);
lu.setFloatValue(value);
return lu;
}
- public static LexicalUnit createIdent(final String s) {
+ public static MockLU createIdent(final String s) {
final MockLU lu = new MockLU(LexicalUnit.SAC_IDENT);
lu.setStringValue(s);
return lu;
}
- public static LexicalUnit createString(final String s) {
+ public static MockLU createString(final String s) {
final MockLU lu = new MockLU(LexicalUnit.SAC_STRING_VALUE);
lu.setStringValue(s);
return lu;
}
- public static LexicalUnit createAttr(final String attributeName) {
+ public static MockLU createAttr(final String attributeName) {
final MockLU result = new MockLU(LexicalUnit.SAC_ATTR);
result.setStringValue(attributeName);
return result;
}
+ public static MockLU createUri(final String uri) {
+ final MockLU result = new MockLU(LexicalUnit.SAC_URI);
+ result.setStringValue(uri);
+ return result;
+ }
+
+ public static MockLU createImage(final MockLU... parameters) {
+ final MockLU result = new MockLU(LexicalUnit.SAC_FUNCTION);
+ result.setFunctionName(CSS.IMAGE_FUNCTION);
+ MockLU firstParameter = null;
+ MockLU lastParameter = null;
+ for (final MockLU parameter : parameters) {
+ if (firstParameter == null) {
+ firstParameter = parameter;
+ }
+ if (lastParameter != null) {
+ lastParameter.setNextLexicalUnit(parameter);
+ parameter.setPreviousLexicalUnit(lastParameter);
+ }
+ lastParameter = parameter;
+ }
+ result.setParameters(firstParameter);
+ return result;
+ }
+
@Override
public String getDimensionUnitText() {
return dimensionUnitText;
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/PropertyTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/PropertyTest.java
index a959da0..48dd2fb 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/PropertyTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/css/PropertyTest.java
@@ -16,11 +16,13 @@
import java.io.StringReader;
import java.util.Iterator;
+import java.util.List;
import org.eclipse.vex.core.internal.core.DisplayDevice;
import org.eclipse.vex.core.internal.io.DocumentReader;
import org.eclipse.vex.core.provisional.dom.IDocument;
import org.eclipse.vex.core.provisional.dom.IElement;
+import org.eclipse.vex.core.provisional.dom.IProcessingInstruction;
import org.junit.Test;
import org.w3c.css.sac.InputSource;
import org.w3c.css.sac.LexicalUnit;
@@ -143,13 +145,65 @@
final IElement parent = document.getRootElement().childElements().first();
final IElement child = parent.childElements().first();
final OutlineContentProperty property = new OutlineContentProperty();
- final MockLU lu = (MockLU) MockLU.createIdent("child");
+ final MockLU lu = MockLU.createIdent("child");
lu.setNextLexicalUnit(MockLU.createIdent("none"));
assertEquals(child, property.calculate(lu, styles, null, parent));
assertEquals(null, property.calculate(lu, styles, null, child));
}
+ @Test
+ public void contentProperty_textualContent() throws Exception {
+ final ContentProperty property = new ContentProperty();
+ final LexicalUnit lu = MockLU.createString("textual content");
+ final List<IPropertyContent> propertyContent = property.calculate(lu, null, null, null);
+ assertEquals(1, propertyContent.size());
+ assertEquals("textual content", propertyContent.get(0).toString());
+ }
+
+ @Test
+ public void contentProperty_attributeDependendContent() throws Exception {
+ final IDocument document = new DocumentReader().read("<root><elem textAttr=\"textual content from attribute\"/></root>");
+ final IElement element = document.getRootElement().childElements().first();
+ final LexicalUnit lu = MockLU.createAttr("textAttr");
+ final List<IPropertyContent> propertyContent = new ContentProperty().calculate(lu, null, null, element);
+ assertEquals(1, propertyContent.size());
+ final IPropertyContent firstContent = propertyContent.get(0);
+ assertEquals("textual content from attribute", firstContent.toString());
+
+ element.setAttribute("textAttr", "changed textual content");
+ assertEquals("changed textual content", firstContent.toString());
+ }
+
+ @Test
+ public void contentProperty_processingInstructionTarget() throws Exception {
+ final IDocument document = new DocumentReader().read("<root><?piTarget?></root>");
+ final IProcessingInstruction pi = (IProcessingInstruction) document.getRootElement().children().first();
+ final LexicalUnit lu = MockLU.createAttr("target");
+ final List<IPropertyContent> propertyContent = new ContentProperty().calculate(lu, null, null, pi);
+ assertEquals(1, propertyContent.size());
+ final IPropertyContent firstContent = propertyContent.get(0);
+ assertEquals("piTarget", firstContent.toString());
+
+ pi.setTarget("anotherTarget");
+ assertEquals("anotherTarget", firstContent.toString());
+ }
+
+ @Test
+ public void contentProperty_image_attributeValue() throws Exception {
+ final IDocument document = new DocumentReader().read("<root><image src=\"image.jpg\"/></root>");
+ final IElement imageElement = document.getRootElement().childElements().first();
+ imageElement.setBaseURI("https://www.eclipse.org");
+ final LexicalUnit lu = MockLU.createImage(MockLU.createAttr("src"));
+ final List<IPropertyContent> propertyContent = new ContentProperty().calculate(lu, null, null, imageElement);
+ assertEquals(1, propertyContent.size());
+ final IPropertyContent firstContent = propertyContent.get(0);
+ assertEquals("https://www.eclipse.org/image.jpg", ((ImageContent) firstContent).getResolvedImageURL().toString());
+
+ imageElement.setAttribute("src", "anotherImage.jpg");
+ assertEquals("https://www.eclipse.org/anotherImage.jpg", ((ImageContent) firstContent).getResolvedImageURL().toString());
+ }
+
private static class DummyDisplayDevice extends DisplayDevice {
public DummyDisplayDevice(final int horizontalPPI, final int verticalPPI) {
this.horizontalPPI = horizontalPPI;
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/AttributeDependendContent.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/AttributeDependendContent.java
new file mode 100644
index 0000000..289424d
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/AttributeDependendContent.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Florian Thienel and others.
+ * 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:
+ * Florian Thienel - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.css;
+
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.provisional.dom.IElement;
+
+public class AttributeDependendContent implements IPropertyContent {
+
+ public final IElement element;
+ public final QualifiedName attributeName;
+
+ public AttributeDependendContent(final IElement element, final QualifiedName attributeName) {
+ this.element = element;
+ this.attributeName = attributeName;
+ }
+
+ @Override
+ public <T> T accept(final IPropertyContentVisitor<T> visitor) {
+ return visitor.visit(this);
+ }
+
+ @Override
+ public String toString() {
+ final String attributeValue = element.getAttributeValue(attributeName);
+ if (attributeValue != null) {
+ return attributeValue;
+ }
+ return "";
+ }
+
+}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CSS.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CSS.java
index a146a86..627a5c9 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CSS.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/CSS.java
@@ -135,6 +135,9 @@
public static final String OUTLINE_CONTENT = "_vex-outline-content";
public static final String INLINE_MARKER = "_vex-inline-marker";
+ // VEX specific functions
+ public static final String IMAGE_FUNCTION = "image";
+
// suffixes to BORDER_XXX
public static final String COLOR_SUFFIX = "-color";
public static final String STYLE_SUFFIX = "-style";
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ContentProperty.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ContentProperty.java
new file mode 100644
index 0000000..ea8b4e3
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ContentProperty.java
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Florian Thienel and others.
+ * 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:
+ * Florian Thienel - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.css;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.provisional.dom.BaseNodeVisitorWithResult;
+import org.eclipse.vex.core.provisional.dom.IElement;
+import org.eclipse.vex.core.provisional.dom.INode;
+import org.eclipse.vex.core.provisional.dom.IProcessingInstruction;
+import org.w3c.css.sac.LexicalUnit;
+
+public class ContentProperty extends AbstractProperty {
+
+ public ContentProperty() {
+ super(CSS.CONTENT);
+ }
+
+ @Override
+ public List<IPropertyContent> calculate(final LexicalUnit lu, final Styles parentStyles, final Styles styles, final INode node) {
+ final List<IPropertyContent> result = new ArrayList<IPropertyContent>();
+
+ LexicalUnit currentLexicalUnit = lu;
+ while (currentLexicalUnit != null) {
+ IPropertyContent propertyContent;
+ switch (currentLexicalUnit.getLexicalUnitType()) {
+ case LexicalUnit.SAC_STRING_VALUE:
+ propertyContent = stringValue(currentLexicalUnit, result);
+ break;
+ case LexicalUnit.SAC_ATTR:
+ propertyContent = attr(currentLexicalUnit, node, result);
+ break;
+ case LexicalUnit.SAC_FUNCTION:
+ if (CSS.IMAGE_FUNCTION.equalsIgnoreCase(currentLexicalUnit.getFunctionName())) {
+ String stylesBaseURI;
+ if (styles != null && styles.getBaseUrl() != null) {
+ stylesBaseURI = styles.getBaseUrl().toString();
+ } else {
+ stylesBaseURI = null;
+ }
+ propertyContent = image(currentLexicalUnit, node, stylesBaseURI);
+ } else {
+ propertyContent = null;
+ }
+ break;
+ default:
+ // ignore other LexicalUnit types
+ propertyContent = null;
+ break;
+ }
+
+ if (propertyContent != null) {
+ result.add(propertyContent);
+ }
+
+ currentLexicalUnit = currentLexicalUnit.getNextLexicalUnit();
+ }
+
+ return result;
+ }
+
+ private static IPropertyContent stringValue(final LexicalUnit lexicalUnit, final List<IPropertyContent> result) {
+ return new TextualContent(lexicalUnit.getStringValue());
+ }
+
+ private static IPropertyContent attr(final LexicalUnit currentLexicalUnit, final INode node, final List<IPropertyContent> result) {
+ final String stringValue = currentLexicalUnit.getStringValue();
+ return node.accept(new BaseNodeVisitorWithResult<IPropertyContent>() {
+ @Override
+ public IPropertyContent visit(final IElement element) {
+ return new AttributeDependendContent(element, new QualifiedName(null, stringValue));
+ }
+
+ @Override
+ public IPropertyContent visit(final IProcessingInstruction pi) {
+ if (CSS.PSEUDO_TARGET.equalsIgnoreCase(stringValue)) {
+ return new ProcessingInstructionTargetContent(pi);
+ }
+ return null;
+ }
+ });
+ }
+
+ private static IPropertyContent uri(final LexicalUnit lexicalUnit) {
+ return new URIContent(lexicalUnit.getStringValue());
+ }
+
+ private static IPropertyContent image(final LexicalUnit lexicalUnit, final INode node, final String stylesBaseURI) {
+ final List<IPropertyContent> parameters = parseImageParameters(lexicalUnit.getParameters(), node);
+ final String baseURI = determineImageBaseURI(parameters, node, stylesBaseURI);
+
+ return new ImageContent(baseURI, parameters);
+ }
+
+ private static List<IPropertyContent> parseImageParameters(final LexicalUnit parameters, final INode node) {
+ final List<IPropertyContent> result = new ArrayList<IPropertyContent>();
+
+ LexicalUnit currentLexicalUnit = parameters;
+ while (currentLexicalUnit != null) {
+ IPropertyContent propertyContent;
+ switch (currentLexicalUnit.getLexicalUnitType()) {
+ case LexicalUnit.SAC_STRING_VALUE:
+ propertyContent = stringValue(currentLexicalUnit, result);
+ break;
+ case LexicalUnit.SAC_ATTR:
+ propertyContent = attr(currentLexicalUnit, node, result);
+ break;
+ case LexicalUnit.SAC_URI:
+ propertyContent = uri(currentLexicalUnit);
+ break;
+ default:
+ // ignore other LexicalUnit types
+ propertyContent = null;
+ break;
+ }
+
+ if (propertyContent != null) {
+ result.add(propertyContent);
+ }
+
+ currentLexicalUnit = currentLexicalUnit.getNextLexicalUnit();
+ }
+
+ return result;
+ }
+
+ private static String determineImageBaseURI(final List<IPropertyContent> parameters, final INode node, final String stylesBaseURI) {
+ for (final IPropertyContent parameter : parameters) {
+ if (parameter instanceof AttributeDependendContent) {
+ return node.getBaseURI();
+ }
+ }
+ return stylesBaseURI;
+ }
+}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IPropertyContentVisitor.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IPropertyContentVisitor.java
index 0beaee1..c9664c5 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IPropertyContentVisitor.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/IPropertyContentVisitor.java
@@ -14,6 +14,12 @@
T visit(TextualContent content);
+ T visit(AttributeDependendContent content);
+
+ T visit(ProcessingInstructionTargetContent content);
+
T visit(URIContent content);
+ T visit(ImageContent content);
+
}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ImageContent.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ImageContent.java
new file mode 100644
index 0000000..2244400
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ImageContent.java
@@ -0,0 +1,54 @@
+package org.eclipse.vex.core.internal.css;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+
+public class ImageContent implements IPropertyContent {
+
+ public final String baseURI;
+ public final List<IPropertyContent> parameters;
+
+ public ImageContent(final String baseURI, final List<IPropertyContent> parameters) {
+ this.baseURI = baseURI;
+ this.parameters = parameters;
+ }
+
+ @Override
+ public <T> T accept(final IPropertyContentVisitor<T> visitor) {
+ return visitor.visit(this);
+ }
+
+ public URL getResolvedImageURL() throws MalformedURLException {
+ final String urlSpecification = getParametersAsString();
+ final URL baseURL = getBaseURL();
+ if (baseURL == null) {
+ return new URL(urlSpecification);
+ } else {
+ return new URL(baseURL, urlSpecification);
+ }
+ }
+
+ private String getParametersAsString() {
+ final StringBuilder string = new StringBuilder();
+ for (final IPropertyContent parameter : parameters) {
+ string.append(parameter.toString());
+ }
+ return string.toString();
+ }
+
+ private URL getBaseURL() throws MalformedURLException {
+ final URL baseURL;
+ if (baseURI == null) {
+ baseURL = null;
+ } else {
+ baseURL = new URL(baseURI);
+ }
+ return baseURL;
+ }
+
+ @Override
+ public String toString() {
+ return "ImageContent [baseURI=" + baseURI + ", urlSpecification=" + getParametersAsString() + "]";
+ }
+}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ProcessingInstructionTargetContent.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ProcessingInstructionTargetContent.java
new file mode 100644
index 0000000..5d760f1
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/ProcessingInstructionTargetContent.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Florian Thienel and others.
+ * 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:
+ * Florian Thienel - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.css;
+
+import org.eclipse.vex.core.provisional.dom.IProcessingInstruction;
+
+public class ProcessingInstructionTargetContent implements IPropertyContent {
+
+ public final IProcessingInstruction processingInstruction;
+
+ public ProcessingInstructionTargetContent(final IProcessingInstruction processingInstruction) {
+ this.processingInstruction = processingInstruction;
+ }
+
+ @Override
+ public <T> T accept(final IPropertyContentVisitor<T> visitor) {
+ return visitor.visit(this);
+ }
+
+ @Override
+ public String toString() {
+ return processingInstruction.getTarget();
+ }
+
+}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheet.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheet.java
index d6dfbdb..568db74 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheet.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/StyleSheet.java
@@ -86,7 +86,9 @@
new BorderWidthProperty(CSS.BORDER_LEFT_WIDTH, CSS.BORDER_LEFT_STYLE, IProperty.Axis.HORIZONTAL),
new BorderWidthProperty(CSS.BORDER_RIGHT_WIDTH, CSS.BORDER_RIGHT_STYLE, IProperty.Axis.HORIZONTAL),
new BorderWidthProperty(CSS.BORDER_TOP_WIDTH, CSS.BORDER_TOP_STYLE, IProperty.Axis.VERTICAL), new BorderSpacingProperty(), new LengthProperty(CSS.HEIGHT, IProperty.Axis.VERTICAL),
- new LengthProperty(CSS.WIDTH, IProperty.Axis.HORIZONTAL), new BackgroundImageProperty(), new OutlineContentProperty(), new InlineMarkerProperty() };
+ new LengthProperty(CSS.WIDTH, IProperty.Axis.HORIZONTAL), new BackgroundImageProperty(), new OutlineContentProperty(), new InlineMarkerProperty(),
+ new ContentProperty()
+ };
private final List<Rule> rules;
private final URL baseUrl;
@@ -268,32 +270,8 @@
styles.setBaseUrl(baseUrl);
- LexicalUnit lexicalUnit;
- lexicalUnit = decls.get(CSS.CONTENT);
- // Content needs special handling, since the value of attr(xxx) may change while editing
- // We pass all valid LexicalUnits to Styles and evaluate there on every access
- final List<LexicalUnit> content = new ArrayList<LexicalUnit>();
- while (lexicalUnit != null) {
- switch (lexicalUnit.getLexicalUnitType()) {
- case LexicalUnit.SAC_STRING_VALUE:
- // content: "A String"
- content.add(lexicalUnit);
- break;
- case LexicalUnit.SAC_ATTR:
- // content: attr(attributeName)
- content.add(lexicalUnit);
- break;
- case LexicalUnit.SAC_URI:
- // content: url("<some URI of an image>")
- content.add(lexicalUnit);
- break;
- }
- lexicalUnit = lexicalUnit.getNextLexicalUnit();
- }
- styles.setContent(content);
-
for (final IProperty property : CSS_PROPERTIES) {
- lexicalUnit = decls.get(property.getName());
+ final LexicalUnit lexicalUnit = decls.get(property.getName());
final Object value = property.calculate(lexicalUnit, parentStyles, styles, node);
styles.put(property.getName(), value);
}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Styles.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Styles.java
index 2840bda..d609345 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Styles.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/Styles.java
@@ -14,10 +14,7 @@
package org.eclipse.vex.core.internal.css;
import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
import java.net.URL;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -25,12 +22,6 @@
import org.eclipse.vex.core.internal.core.Color;
import org.eclipse.vex.core.internal.core.FontSpec;
import org.eclipse.vex.core.internal.core.Length;
-import org.eclipse.vex.core.provisional.dom.BaseNodeVisitor;
-import org.eclipse.vex.core.provisional.dom.BaseNodeVisitorWithResult;
-import org.eclipse.vex.core.provisional.dom.IElement;
-import org.eclipse.vex.core.provisional.dom.INode;
-import org.eclipse.vex.core.provisional.dom.IProcessingInstruction;
-import org.w3c.css.sac.LexicalUnit;
/**
* Represents the computed style properties for a particular element.
@@ -67,7 +58,6 @@
*/
private final Map<String, Styles> pseudoElementStyles = new HashMap<String, Styles>();
- private List<LexicalUnit> contentLexicalUnits;
private FontSpec font;
private URL baseUrl;
@@ -183,7 +173,10 @@
* @return <code>true</code> if the stylesheet defined content for this element.
*/
public boolean isContentDefined() {
- return contentLexicalUnits.size() > 0;
+ if (!values.containsKey(CSS.CONTENT)) {
+ return false;
+ }
+ return !getContent().isEmpty();
}
/**
@@ -195,87 +188,17 @@
* @param node
* The INode to get attr(...) values from
*/
- public List<String> getTextualContent(final INode node) {
- final List<String> content = new ArrayList<String>();
- for (final LexicalUnit lexicalUnit : contentLexicalUnits) {
- switch (lexicalUnit.getLexicalUnitType()) {
- case LexicalUnit.SAC_STRING_VALUE:
- // content: "A String"
- content.add(lexicalUnit.getStringValue());
- break;
- case LexicalUnit.SAC_ATTR:
- // content: attr(attributeName)
- final LexicalUnit currentLexicalUnit = lexicalUnit;
- node.accept(new BaseNodeVisitor() {
- @Override
- public void visit(final IElement element) {
- final String attributeValue = element.getAttributeValue(currentLexicalUnit.getStringValue());
- if (attributeValue != null) {
- content.add(attributeValue);
- }
- }
-
- @Override
- public void visit(final IProcessingInstruction pi) {
- if (currentLexicalUnit.getStringValue().equalsIgnoreCase(CSS.PSEUDO_TARGET)) {
- content.add(pi.getTarget());
- }
- }
- });
- break;
- }
+ public String getTextualContent() {
+ final StringBuilder string = new StringBuilder();
+ for (final IPropertyContent content : getContent()) {
+ string.append(content.toString());
}
- return content;
+ return string.toString();
}
- public List<IPropertyContent> getAllContent(final INode node) {
- final List<IPropertyContent> allContent = new ArrayList<IPropertyContent>();
- for (final LexicalUnit lexicalUnit : contentLexicalUnits) {
- final IPropertyContent content = getContent(lexicalUnit, node);
- if (content != null) {
- allContent.add(content);
- }
- }
- return allContent;
- }
-
- private IPropertyContent getContent(final LexicalUnit lexicalUnit, final INode node) {
- switch (lexicalUnit.getLexicalUnitType()) {
- case LexicalUnit.SAC_STRING_VALUE:
- // content: "A String"
- return new TextualContent(lexicalUnit.getStringValue());
- case LexicalUnit.SAC_ATTR:
- // content: attr(attributeName)
- final LexicalUnit currentLexicalUnit = lexicalUnit;
- return node.accept(new BaseNodeVisitorWithResult<IPropertyContent>() {
- @Override
- public IPropertyContent visit(final IElement element) {
- final String attributeValue = element.getAttributeValue(currentLexicalUnit.getStringValue());
- if (attributeValue != null) {
- return new TextualContent(attributeValue);
- }
- return null;
- }
-
- @Override
- public IPropertyContent visit(final IProcessingInstruction pi) {
- if (currentLexicalUnit.getStringValue().equalsIgnoreCase(CSS.PSEUDO_TARGET)) {
- return new TextualContent(pi.getTarget());
- }
- return null;
- }
- });
- case LexicalUnit.SAC_URI:
- // content: url("<some URI of an image>")
- try {
- return new URIContent(new URI(lexicalUnit.getStringValue()));
- } catch (final URISyntaxException e) {
- e.printStackTrace();
- return null;
- }
- default:
- return null;
- }
+ @SuppressWarnings("unchecked")
+ public List<IPropertyContent> getContent() {
+ return (List<IPropertyContent>) values.get(CSS.CONTENT);
}
/**
@@ -405,16 +328,6 @@
}
/**
- * Sets the LexicalUnits of the <code>content</code> property.
- *
- * @param content
- * <code>List</code> of <code>LexicalUnits</code> objects defining the content.
- */
- public void setContent(final List<LexicalUnit> content) {
- contentLexicalUnits = content;
- }
-
- /**
* Sets the value of the <code>font</code> property.
*
* @param font
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/URIContent.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/URIContent.java
index 4c06f2b..11ed460 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/URIContent.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/css/URIContent.java
@@ -11,12 +11,13 @@
package org.eclipse.vex.core.internal.css;
import java.net.URI;
+import java.net.URISyntaxException;
public class URIContent implements IPropertyContent {
- public final URI uri;
+ public final String uri;
- public URIContent(final URI uri) {
+ public URIContent(final String uri) {
this.uri = uri;
}
@@ -29,4 +30,8 @@
public String toString() {
return uri.toString();
}
+
+ public URI uriValue() throws URISyntaxException {
+ return new URI(uri);
+ }
}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutUtils.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutUtils.java
index dbe570d..c578a65 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutUtils.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/layout/LayoutUtils.java
@@ -77,12 +77,7 @@
* The node passed to Styles#getContent (to get attr values from)
*/
public static String getGeneratedContent(final LayoutContext context, final Styles styles, final INode node) {
- final List<String> content = styles.getTextualContent(node);
- final StringBuffer sb = new StringBuffer();
- for (final String string : content) {
- sb.append(string); // TODO: change to ContentPart
- }
- return sb.toString();
+ return styles.getTextualContent();
}
/**
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/visualization/CssBasedBoxModelBuilder.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/visualization/CssBasedBoxModelBuilder.java
index cfc17ef..72e85e9 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/visualization/CssBasedBoxModelBuilder.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/visualization/CssBasedBoxModelBuilder.java
@@ -25,6 +25,7 @@
import static org.eclipse.vex.core.internal.visualization.CssBoxFactory.staticText;
import static org.eclipse.vex.core.internal.visualization.CssBoxFactory.textContent;
+import java.net.MalformedURLException;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
@@ -41,9 +42,12 @@
import org.eclipse.vex.core.internal.boxes.Paragraph;
import org.eclipse.vex.core.internal.boxes.RootBox;
import org.eclipse.vex.core.internal.boxes.TextContent;
+import org.eclipse.vex.core.internal.css.AttributeDependendContent;
import org.eclipse.vex.core.internal.css.CSS;
import org.eclipse.vex.core.internal.css.IPropertyContent;
import org.eclipse.vex.core.internal.css.IPropertyContentVisitor;
+import org.eclipse.vex.core.internal.css.ImageContent;
+import org.eclipse.vex.core.internal.css.ProcessingInstructionTargetContent;
import org.eclipse.vex.core.internal.css.StyleSheet;
import org.eclipse.vex.core.internal.css.Styles;
import org.eclipse.vex.core.internal.css.Styles.PseudoElement;
@@ -308,7 +312,7 @@
}
private static <P extends IParentBox<IInlineBox>> P visualizeContentProperty(final INode node, final Styles styles, final P parent) {
- for (final IPropertyContent part : styles.getAllContent(node)) {
+ for (final IPropertyContent part : styles.getContent()) {
final IInlineBox box = part.accept(new IPropertyContentVisitor<IInlineBox>() {
@Override
public IInlineBox visit(final TextualContent content) {
@@ -316,12 +320,34 @@
}
@Override
+ public IInlineBox visit(final AttributeDependendContent content) {
+ return staticText(content.toString(), styles);
+ }
+
+ @Override
+ public IInlineBox visit(final ProcessingInstructionTargetContent content) {
+ return staticText(content.toString(), styles);
+ }
+
+ @Override
public IInlineBox visit(final URIContent content) {
final String imageUri = content.uri.toString();
final Image image = new Image();
image.setImageUrl(styles.resolveUrl(imageUri));
return image;
}
+
+ @Override
+ public IInlineBox visit(final ImageContent content) {
+ final Image image = new Image();
+ try {
+ image.setImageUrl(content.getResolvedImageURL());
+ } catch (final MalformedURLException e) {
+ // TODO log error, render error information
+ e.printStackTrace();
+ }
+ return image;
+ }
});
if (box != null) {
parent.appendChild(box);
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/swt/SwtGraphics.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/swt/SwtGraphics.java
index ed3c7c6..5d504bc 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/swt/SwtGraphics.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/swt/SwtGraphics.java
@@ -240,6 +240,10 @@
}
private static ImageData[] loadImageData(final URL url) {
+ if (url == null) {
+ return null;
+ }
+
final ImageLoader imageLoader = new ImageLoader();
try {
final InputStream in = url.openStream();