com.cladonia.xml.viewer.Viewer.java Source code

Java tutorial

Introduction

Here is the source code for com.cladonia.xml.viewer.Viewer.java

Source

/*
 * $Id: Viewer.java,v 1.11 2004/11/05 11:44:52 edankert Exp $
 *
 * Copyright (C) 2002-2003, Cladonia Ltd. All rights reserved.
 *
 * This software is the proprietary information of Cladonia Ltd.  
 * Use is subject to license terms.
 */
package com.cladonia.xml.viewer;

import java.awt.BorderLayout;
import java.awt.Rectangle;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.List;
import java.util.Vector;

import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreePath;

import org.dom4j.ProcessingInstruction;
import org.dom4j.tree.DefaultDocument;

import com.cladonia.xml.ExchangerDocument;
import com.cladonia.xml.ExchangerDocumentEvent;
import com.cladonia.xml.ExchangerDocumentListener;
import com.cladonia.xml.XElement;
import com.cladonia.xngreditor.ExchangerEditor;
import com.cladonia.xngreditor.ExchangerView;
import com.cladonia.xngreditor.ViewTreePanel;
import com.cladonia.xngreditor.XngrImageLoader;
import com.cladonia.xngreditor.properties.TextPreferences;

/**
 * Shows a tree view of a XML document.
 *
 * @version   $Revision: 1.11 $, $Date: 2004/11/05 11:44:52 $
 * @author Dogsbay
 */
public class Viewer extends ViewTreePanel implements ExchangerDocumentListener {
    private static final boolean DEBUG = false;
    private static final ImageIcon ICON = XngrImageLoader.get()
            .getImage("com/cladonia/xml/viewer/icons/ViewerIcon.gif");
    private XmlTree tree = null;
    private JScrollPane scrollPane = null;

    private ComponentAdapter resizeListener = null;
    private JLabel universalNameLabel = null;
    private JLabel namespacesLabel = null;
    private JLabel valuesLabel = null;
    private JLabel attributesLabel = null;
    private JLabel commentsLabel = null;

    private ExchangerDocument document = null;
    private ViewerProperties properties = null;
    private ExchangerEditor xngreditor = null;
    private ExchangerView view = null;

    private boolean showNamespaces = false;
    private boolean showAttributes = false;
    private boolean showValues = false;
    private boolean showComments = false;
    private boolean showInline = false;
    private boolean showPI = false;

    private boolean hasLatest = false;
    public static final String XNGR_DUMMY_ROOT = "xngr_dummy_element";

    /**
     * Constructs an explorer view with the ExplorerProperties supplied.
     *
     * @param properties the explorer properties.
     */
    public Viewer(ExchangerEditor parent, ViewerProperties props, ExchangerView _view) {
        super(new BorderLayout());

        this.properties = props;
        this.xngreditor = parent;
        this.view = _view;

        try {
            tree = new XmlTree();
        } catch (Exception e) {
            e.printStackTrace();
            // should not happen
        }

        tree.addTreeSelectionListener(new TreeSelectionListener() {
            public void valueChanged(TreeSelectionEvent e) {
                TreePath path = tree.getSelectionPath();
                if (path != null) {
                    XmlElementNode node = (XmlElementNode) path.getLastPathComponent();
                    XElement element = node.getElement();

                    if (element != null && tree != null) {
                        //                  universalNameLabel.setText( node.getElement().getUniversalName());
                        xngreditor.getXPathEditor().setXPath(element);
                        xngreditor.getNavigator().setSelectedElement(element);
                        xngreditor.getHelper().setElement(element);

                        Rectangle bounds = tree.getPathBounds(path);

                        if (bounds != null) {
                            int y = bounds.y;
                            y = y - scrollPane.getViewport().getViewRect().y;

                            xngreditor.synchronise(view, element, node.isEndTag(), y);
                        }
                    }
                    //               } else {
                    //                  universalNameLabel.setText( "");
                    //                  xpath.getEditor().setItem( null);
                    //               }
                    //            } else {
                    //               universalNameLabel.setText( null);
                }
            }
        });

        scrollPane = new JScrollPane(tree, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

        /**
         * Work around to make sure the scroll pane shows the vertical 
         * scrollbar for the first time when resized to a size small enough.
         * JDK 1.3.0-C 
         *
         * Got work around from Bug ID: 4243631 (It should be fixed...)
         *
         * ED: Check with JDK1.4
         */
        resizeListener = new ComponentAdapter() {
            public void componentResized(ComponentEvent e) {
                scrollPane.doLayout();
            }
        };

        scrollPane.getViewport().addComponentListener(resizeListener);

        this.setBorder(new EmptyBorder(0, 0, 0, 0));
        this.add(scrollPane, BorderLayout.CENTER);

        showAttributes = properties.isShowAttributes();
        showNamespaces = properties.isShowNamespaces();
        showValues = properties.isShowValues();
        showComments = properties.isShowComments();
        showInline = properties.isShowInline();
        showPI = properties.isShowPI();

        ((XmlCellRenderer) tree.getCellRenderer()).setFont(TextPreferences.getBaseFont());

        tree.addFocusListener(new FocusListener() {
            public void focusGained(FocusEvent e) {
                view.setFocussed();
            }

            public void focusLost(FocusEvent e) {
            }
        });
    }

    public void updateHelper() {
        TreePath path = tree.getSelectionPath();

        if (path != null) {
            XmlElementNode node = (XmlElementNode) path.getLastPathComponent();
            XElement element = node.getElement();

            if (element != null) {
                xngreditor.getHelper().setElement(node.getElement());
            }
        }
    }

    /**
     * Check to find out if namespaces should be visible.
     *
     * @return true if namespaces are visible.
     */
    public XElement getSelectedElement() {
        return tree.getSelectedElement();
    }

    public void setFocus() {
        if (!tree.hasFocus()) {
            tree.requestFocusInWindow();
        }
    }

    /**
     * Update the preferences.
     */
    public void updatePreferences() {
        ((XmlCellRenderer) tree.getCellRenderer()).setFont(TextPreferences.getBaseFont());

        if (propertiesUpdated()) {
            update();
        } else {
            tree.updateUI();
        }
    }

    /**
     * Adds an element to the list of selected elements.
     *
     * @param element the element to select.
     */
    public void addSelectedElement(XElement element) {
        tree.setSelectedNode(element, false);
    }

    /**
     * Clears the current selection.
     */
    public void clearSelection() {
        tree.clearSelection();
    }

    public void setProperties() {
    }

    /**
     * Check to find out if namespaces should be visible.
     *
     * @return true if namespaces are visible.
     */
    public void setSelectedElement(XElement element, boolean end, int y) {
        tree.clearSelection();

        if (element != null) {
            tree.setSelectedNode(element, end);

            if (y != -1 && tree.getSelectionPath() != null) {
                Rectangle r = tree.getVisibleRect();
                Rectangle sr = tree.getPathBounds(tree.getSelectionPath());
                sr.height = r.height;
                sr.y = sr.y - y;

                if (r.height > y && sr.y >= 0) {
                    tree.scrollRectToVisible(sr);

                    tree.revalidate();
                    tree.repaint();
                }
            }
        }
    }

    //Check to see it the properties have been updated.
    private boolean propertiesUpdated() {
        if ((properties.isShowAttributes() == showAttributes) && (properties.isShowNamespaces() == showNamespaces)
                && (properties.isShowValues() == showValues) && (properties.isShowComments() == showComments)
                && (properties.isShowInline() == showInline) && (properties.isShowPI() == showPI)) {
            return false;
        }

        showAttributes = properties.isShowAttributes();
        showNamespaces = properties.isShowNamespaces();
        showValues = properties.isShowValues();
        showComments = properties.isShowComments();
        showInline = properties.isShowInline();
        showPI = properties.isShowPI();

        return true;
    }

    /**
     * Check to find out if namespaces should be visible.
     *
     * @return true if namespaces are visible.
     */
    public boolean showNamespaces() {
        boolean result = properties.isShowNamespaces();
        if (DEBUG)
            System.out.println("Viewer.showNamespaces() [" + result + "]");
        return result;
    }

    /**
     * Check to find out if attributes should be visible.
     *
     * @return true if attributes are visible.
     */
    public boolean showAttributes() {
        boolean result = properties.isShowAttributes();
        if (DEBUG)
            System.out.println("Viewer.showAttributes() [" + result + "]");
        return result;
    }

    /**
     * Check to find out if comments should be visible.
     *
     * @return true if comments are visible.
     */
    public boolean showComments() {
        boolean result = properties.isShowComments();
        if (DEBUG)
            System.out.println("Viewer.showComments() [" + result + "]");
        return result;
    }

    /**
     * Check to find out if PIs should be visible.
     *
     * @return true if PIs are visible.
     */
    public boolean showPI() {
        boolean result = properties.isShowPI();
        return result;
    }

    /**
     * Check to find out if CDATAs should be visible.
     *
     * @return true if CDATA sections are visible.
     */
    public boolean showCDATA() {
        boolean result = properties.isShowInline();
        return result;
    }

    /**
     * Check to find out if mixed should be shown inline
     *
     * @return true if CDATA sections are visible.
     */
    public boolean showInline() {
        boolean result = properties.isShowInline();
        return result;
    }

    private void update() {
        if (tree != null && document != null) {
            if (showPI()) {
                XElement dummyElement = new XElement(XNGR_DUMMY_ROOT);
                DefaultDocument doc = (DefaultDocument) document.getDocument();
                List pis = doc.processingInstructions();

                Vector allPIs = new Vector();
                ;
                for (int i = 0; i < pis.size(); i++) {
                    ProcessingInstruction pi = (ProcessingInstruction) pis.get(i);
                    if (!addedPI(allPIs, pi.getTarget() + pi.getText())) {
                        dummyElement.addProcessingInstruction(pi.getTarget(), pi.getText());
                        allPIs.add(pi.getTarget() + pi.getText());
                    }
                }

                XmlElementNode dummyRoot = new XmlElementNode(this, dummyElement);
                XmlElementNode node = new XmlElementNode(this, (XElement) document.getRoot());
                dummyRoot.add(node);
                tree.setRoot(dummyRoot);
                tree.expand(4);

                tree.setRootVisible(false);
            } else {
                XmlElementNode node = new XmlElementNode(this, (XElement) document.getRoot());
                tree.setRoot(node);
                tree.expand(3);

                tree.setRootVisible(true);
            }
        }
    }

    // to avoid dom4j bug where the processing instructions are returned twice from the document
    private boolean addedPI(Vector allPIs, String newPI) {
        boolean found = false;
        for (int i = 0; i < allPIs.size(); i++) {
            String oldPI = (String) allPIs.get(i);
            if (oldPI.equals(newPI)) {
                found = true;
            }
        }
        return found;
    }

    /**
     * Check to find out if values should be visible.
     *
     * @return true if values are visible.
     */
    public boolean showValues() {
        boolean result = properties.isShowValues();
        if (DEBUG)
            System.out.println("Viewer.showValues() [" + result + "]");
        return result;
    }

    /**
     * Collapses all the nodes in the tree.
     */
    public void collapseAll() {
        tree.collapseAll();

        if (showPI())
            tree.expand(2);
        else
            tree.expand(1);
    }

    /**
     * Collapses all the nodes in the tree.
     *
     * @param node the node to collapse all nodes for.
     */
    public void collapseNode(XmlElementNode node) {
        tree.collapseNode(node);
    }

    /**
     * Expands all the nodes in the tree.
     */
    public void expandAll() {
        tree.expandAll();
    }

    /**
     * Expands all the nodes in the tree from this node down.
     *
     * @param node the node to expand all nodes for.
     */
    public void expandNode(XmlElementNode node) {
        tree.expandNode(node);
    }

    /**
     * Returns the icon
     */
    public ImageIcon getIcon() {
        return ICON;
    }

    public void setDocument(ExchangerDocument document) {
        if (DEBUG)
            System.out.println("Viewer.setDocument( " + document + ")");

        if (this.document != null) {
            this.document.removeListener(this);
        }

        this.document = document;

        if (document != null) {
            document.addListener(this);
        }

        if (document != null && !document.isError()) {

            if (showPI()) {
                XElement dummyElement = new XElement(XNGR_DUMMY_ROOT);
                DefaultDocument doc = (DefaultDocument) document.getDocument();
                List pis = doc.processingInstructions();
                for (int i = 0; i < pis.size(); i++) {
                    ProcessingInstruction pi = (ProcessingInstruction) pis.get(i);
                    dummyElement.addProcessingInstruction(pi.getTarget(), pi.getText());
                }

                XmlElementNode dummyRoot = new XmlElementNode(this, dummyElement);
                XmlElementNode node = new XmlElementNode(this, (XElement) document.getRoot());
                dummyRoot.add(node);
                tree.setRoot(dummyRoot);
                tree.expand(4);

                tree.setRootVisible(false);
            } else {
                XmlElementNode node = new XmlElementNode(this, (XElement) document.getRoot());
                tree.setRoot(node);
                tree.expand(3);

                tree.setRootVisible(true);
            }

        } else {
            tree.setRoot(null);
        }

        hasLatest = true;
    }

    public boolean hasLatestInformation() {
        return hasLatest;
    }

    // Implementation of the XDocumentListener interface...   
    public void documentUpdated(ExchangerDocumentEvent event) {
        if (DEBUG)
            System.out.println("Viewer.documentUpdated( " + event + ")");

        hasLatest = false;
    }

    public void documentDeleted(ExchangerDocumentEvent event) {
    }

    public void cleanup() {
        tree.cleanup();

        scrollPane.getViewport().removeComponentListener(resizeListener);

        removeAll();

        finalize();
    }

    protected void finalize() {
        tree = null;
        scrollPane = null;

        universalNameLabel = null;
        namespacesLabel = null;
        valuesLabel = null;
        attributesLabel = null;
        commentsLabel = null;

        document = null;
        properties = null;
        xngreditor = null;
    }
}