org.vectomatic.svg.samples.client.xpath.XPathSample.java Source code

Java tutorial

Introduction

Here is the source code for org.vectomatic.svg.samples.client.xpath.XPathSample.java

Source

/**********************************************
 * Copyright (C) 2009 Lukas Laag
 * This file is part of lib-gwt-svg-samples.
 * 
 * libgwtsvg-samples is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * libgwtsvg-samples is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with libgwtsvg-samples.  If not, see http://www.gnu.org/licenses/
 **********************************************/
package org.vectomatic.svg.samples.client.xpath;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.vectomatic.dom.svg.impl.Attr;
import org.vectomatic.dom.svg.impl.NamedNodeMap;
import org.vectomatic.dom.svg.ui.SVGImage;
import org.vectomatic.dom.svg.ui.SVGResource;
import org.vectomatic.dom.svg.ui.SVGResource.Validated;
import org.vectomatic.dom.svg.utils.DOMHelper;
import org.vectomatic.dom.svg.utils.SVGConstants;
import org.vectomatic.dom.svg.utils.SVGPrefixResolver;
import org.vectomatic.svg.samples.client.Main;
import org.vectomatic.svg.samples.client.Main.MainBundle;
import org.vectomatic.svg.samples.client.SampleBase;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.PreElement;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.dom.client.Text;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TabLayoutPanel;
import com.google.gwt.user.client.ui.TextBox;

/**
 * Class to demonstrate the use of XPaths to navigate in SVG documents
 * @author laaglu
 */
public class XPathSample extends SampleBase {
    interface XmlCssResource extends CssResource {
        public String element();

        public String attribute();

        public String text();

        public String comment();

        public String markup();

        public String selected();

        public String root();
    }

    interface XPathBundle extends ClientBundle {
        public static XPathBundle INSTANCE = GWT.create(XPathBundle.class);

        @Source("xml.css")
        public XmlCssResource css();

        @Validated(validated = false)
        @Source("pizza_pepperoni_bw.svg")
        public SVGResource pizza();
    }

    interface XPathSampleBinder extends UiBinder<TabLayoutPanel, XPathSample> {
    }

    private static XPathSampleBinder binder = GWT.create(XPathSampleBinder.class);

    @UiField(provided = true)
    public static XPathBundle xpathBundle = XPathBundle.INSTANCE;
    @UiField(provided = true)
    public static MainBundle mainBundle = Main.mainBundle;
    /**
     * A Text box to enter XPath expressions
     */
    @UiField
    TextBox xpathBox;
    /**
     * A button to request evaluation of the xpath expression
     */
    @UiField
    Button evaluateButton;
    /**
     * Checkbox to request continuous evaluation of xpath expressions
     * as they are typed
     */
    @UiField
    CheckBox evaluateCheckBox;
    /**
     * A label to display XPath parsing error message
     */
    @UiField
    Label errorLabel;
    /**
     * A sample SVG image
     */
    @UiField
    SVGImage svgImage;
    /**
     * A colorized version of the SVG source XML text
     */
    @UiField
    HTML xmlContainer;

    /**
     * The root document
     */
    private Document doc = Document.get();
    /**
     * The CSS used to colorize text
     */
    private XmlCssResource css = xpathBundle.css();
    /**
     * Maps SVG nodes to bits of XML colorized text
     */
    private Map<Node, SpanElement> nodeToSpan = new HashMap<Node, SpanElement>();
    /**
     * The bits of XML colorized text corresponding to the SVG
     * nodes selected by the XPath expression
     */
    private List<Element> xpathSpans;
    /**
     * The SVG elements selected by the XPath expression
     */
    private List<Element> svgElements;
    /**
     * To resolve namespace prefixes
     */
    private SVGPrefixResolver resolver;

    @Override
    public TabLayoutPanel getPanel() {
        if (tabPanel == null) {
            tabPanel = binder.createAndBindUi(this);
            tabPanel.setTabText(0, "XPath");
            createCodeTabs("XPathSample");

            css.ensureInjected();
            xpathSpans = new ArrayList<Element>();
            svgElements = new ArrayList<Element>();
            PreElement pre = doc.createPreElement();
            visit(svgImage.getElement(), pre);
            pre.addClassName(css.root());
            xmlContainer.getElement().appendChild(pre);
            resolver = new SVGPrefixResolver() {
                {
                    prefixToUri.put("i", "http://ns.adobe.com/AdobeIllustrator/10.0/");
                    prefixToUri.put("cc", "http://web.resource.org/cc/");
                    prefixToUri.put("dc", "http://purl.org/dc/elements/1.1/");
                    prefixToUri.put("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
                }
            };
            evaluate();
        }
        return tabPanel;
    }

    @UiHandler("evaluateButton")
    public void evaluate(ClickEvent event) {
        evaluate();
    }

    @UiHandler("evaluateCheckBox")
    public void checkbox(ClickEvent event) {
        evaluateButton.setEnabled(!evaluateCheckBox.getValue());
    }

    @UiHandler("xpathBox")
    public void keyUp(KeyUpEvent event) {
        if (evaluateCheckBox.getValue()) {
            evaluate();
        }
    }

    public void evaluate() {
        String error = "";
        try {
            for (Element span : xpathSpans) {
                span.removeClassName(css.selected());
            }
            xpathSpans.clear();
            for (Element svgElement : svgElements) {
                svgElement.setAttribute(SVGConstants.SVG_FILL_ATTRIBUTE, "#FFFFFF");
            }
            svgElements.clear();

            String expr = xpathBox.getText();
            GWT.log(expr);
            Iterator<Node> iterator = DOMHelper.evaluateNodeListXPath(svgImage.getElement(), expr, resolver);
            while (iterator.hasNext()) {
                Node node = iterator.next();
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    svgElements.add(node.<Element>cast());
                }
                Element span = nodeToSpan.get(node);
                xpathSpans.add(span);
            }
            for (Element span : xpathSpans) {
                span.addClassName(css.selected());
            }
            for (Element svgElement : svgElements) {
                svgElement.setAttribute(SVGConstants.SVG_FILL_ATTRIBUTE, "green");
            }
        } catch (Throwable t) {
            error = t.getMessage();
        }
        errorLabel.setText(error);
    }

    private SpanElement createMarkup(String markup) {
        SpanElement markupSpan = doc.createSpanElement();
        markupSpan.addClassName(css.markup());
        markupSpan.appendChild(doc.createTextNode(markup));
        return markupSpan;
    }

    private void visit(Node node, Element parentSpan) {
        SpanElement span = doc.createSpanElement();
        nodeToSpan.put(node, span);

        parentSpan.appendChild(span);
        NodeList<Node> childNodes = node.getChildNodes();
        switch (node.getNodeType()) {
        case Node.ELEMENT_NODE: {
            Element element = node.<Element>cast();
            span.addClassName(css.element());

            // Populate the span with a start tag
            span.appendChild(createMarkup("<"));
            String tagName = element.getTagName();
            int index = tagName.indexOf(":");
            if (index != -1) {
                span.appendChild(doc.createTextNode(tagName.substring(0, index)));
                span.appendChild(createMarkup(":"));
                span.appendChild(doc.createTextNode(tagName.substring(index + 1)));
            } else {
                span.appendChild(doc.createTextNode(tagName));
            }

            // Create the attribute nodes spans
            NamedNodeMap<Attr> attributes = DOMHelper.getAttributes(element);
            for (int i = 0, length = attributes.getLength(); i < length; i++) {
                span.appendChild(doc.createTextNode(" "));

                SpanElement attrSpan = doc.createSpanElement();
                attrSpan.addClassName(css.attribute());
                span.appendChild(attrSpan);
                Attr attr = attributes.item(i);
                nodeToSpan.put(attr, attrSpan);

                String attrName = attr.getName();
                index = attrName.indexOf(":");
                if (index != -1) {
                    attrSpan.appendChild(doc.createTextNode(attrName.substring(0, index)));
                    attrSpan.appendChild(createMarkup(":"));
                    attrSpan.appendChild(doc.createTextNode(attrName.substring(index + 1)));
                } else {
                    attrSpan.appendChild(doc.createTextNode(attrName));
                }
                attrSpan.appendChild(createMarkup("=\""));
                attrSpan.appendChild(doc.createTextNode(attr.getValue()));
                attrSpan.appendChild(createMarkup("\""));
            }
            span.appendChild(createMarkup(childNodes.getLength() > 0 ? ">" : "/>"));
        }
            break;
        case Node.TEXT_NODE: {
            // Populate span with text
            Text text = node.<Text>cast();
            span.addClassName(css.text());
            span.appendChild(doc.createTextNode(text.getData()));
        }
            break;
        }

        for (int i = 0, count = node.getChildCount(); i < count; i++) {
            visit(childNodes.getItem(i), span);
        }

        if (childNodes.getLength() > 0 && node.getNodeType() == Node.ELEMENT_NODE) {
            Element element = node.<Element>cast();
            span.addClassName(css.element());

            // Populate the span with a close tag
            span.appendChild(createMarkup("</"));
            String tagName = element.getTagName();
            int index = tagName.indexOf(":");
            if (index != -1) {
                span.appendChild(doc.createTextNode(tagName.substring(0, index)));
                span.appendChild(createMarkup(":"));
                span.appendChild(doc.createTextNode(tagName.substring(index + 1)));
            } else {
                span.appendChild(doc.createTextNode(tagName));
            }
            span.appendChild(createMarkup(">"));
        }
    }

}