/*
 * (C) Copyright IBM Corp. 1997-1998  All rights reserved.
 *
 * US Government Users Restricted Rights Use, duplication or
 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
 *
 * The program is provided "as is" without any warranty express or
 * implied, including the warranty of non-infringement and the implied
 * warranties of merchantibility and fitness for a particular purpose.
 * IBM will not be liable for any damages suffered by you as a result
 * of using the Program. In no event will IBM be liable for any
 * special, indirect or consequential damages or lost profits even if
 * IBM has been advised of the possibility of their occurrence. IBM
 * will not be liable for any third party claims against you.
 */

package com.ibm.xml.sample;

import com.ibm.xml.parser.Child;
import com.ibm.xml.parser.Parser;
import com.ibm.xml.parser.Stderr;
import com.ibm.xml.parser.TXDocument;
import com.ibm.xml.parser.util.TreeFactory;
import com.ibm.xml.xpointer.Pointed.Item;
import com.ibm.xml.xpointer.Pointed;
import com.ibm.xml.xpointer.XPointer;
import com.ibm.xml.xpointer.XPointerParseException;
import com.ibm.xml.xpointer.XPointerParser;
import com.sun.java.swing.JButton;
import com.sun.java.swing.JComponent;
import com.sun.java.swing.JFrame;
import com.sun.java.swing.JLabel;
import com.sun.java.swing.JMenu;
import com.sun.java.swing.JMenuBar;
import com.sun.java.swing.JMenuItem;
import com.sun.java.swing.JPanel;
import com.sun.java.swing.JScrollPane;
import com.sun.java.swing.JTextField;
import com.sun.java.swing.JTree;
import com.sun.java.swing.UIManager;
import com.sun.java.swing.UnsupportedLookAndFeelException;
import com.sun.java.swing.event.MenuEvent;
import com.sun.java.swing.event.MenuListener;
import com.sun.java.swing.event.TreeSelectionEvent;
import com.sun.java.swing.event.TreeSelectionListener;
import com.sun.java.swing.tree.DefaultMutableTreeNode;
import com.sun.java.swing.tree.TreeCellRenderer;
import com.sun.java.swing.tree.TreeNode;
import com.sun.java.swing.tree.TreePath;
import com.sun.java.swing.tree.TreeSelectionModel;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.util.Enumeration;
import java.util.Vector;
import org.w3c.dom.Node;

/**
 *
 * @version 1.1
 * @author TAMURA Kent &lt;kent@trl.ibm.co.jp&gt;
 */
public class XPointerDemo extends JFrame implements java.awt.event.ActionListener {
    public static void main(String[] argv) {
        if (1 != argv.length) {
            System.err.println("Require 1 filename");
            System.exit(1);
        }
        String fname = argv[0];
        try {
            Parser p = new Parser(fname);
            p.setElementFactory(new TreeFactory());
            TXDocument doc = p.readStream(p.getInputStream(fname, null, Stderr.file2URL(fname).toString()));
            new XPointerDemo("XPointer demonstration program", doc).show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    UIManager.LookAndFeelInfo[] m_alooks = null;
    JTree m_tree;
    JScrollPane m_scrollpane;
    JTextField m_text;
    JButton m_button;
    Vector components = new Vector();
    TXDocument m_doc;
    boolean m_byuser = false;

    public void actionPerformed(java.awt.event.ActionEvent e) {
        //System.err.println("ACTION: "+e.getActionCommand()+", "+e.paramString());
        String cmd = e.getActionCommand();
        if (e.getSource() == m_text || cmd.equals("Go")) {
            m_byuser = true;
            try {
                m_tree.clearSelection();
                XPointer xp = new XPointerParser().parse(m_text.getText());
                //System.err.println("XPointer: "+xp);
                Pointed pointed = xp.point(m_doc);
                if (pointed.size() == 0) {
                    new MessageBox(this, "Message:", "Can't find such a node.  XML for Java now doesn't support html() origin() string() span().").show();
                } else {
                    Enumeration en = pointed.elements();
                     while (en.hasMoreElements()) {
                        Item it = (Item)en.nextElement();
                        if (it.type == Pointed.T_NODE || it.type == Pointed.T_STRINGINNODE) {
                            Node ch = it.node;
                            Vector v = new Vector();
                            while (ch != null) {
                                v.insertElementAt(ch, 0);
                                ch = ch.getParentNode();
                            }
                            Object[] arr = new Object[v.size()];
                            v.copyInto(arr);
                            m_tree.addSelectionPath(new TreePath(arr));
                        }
                     }
                }
            } catch (XPointerParseException xex) {
                new MessageBox(this, "Message:", xex.toString()).show();
            }
            m_byuser = false;
            return;
        }
        for (int i = 0;  i < m_alooks.length;  i ++) {
            if (cmd.equals(m_alooks[i].getName())) {
                try {
                    UIManager.setLookAndFeel(m_alooks[i].getClassName());
                    for (int j = 0;  j < this.components.size();  j ++)
                        ((JComponent)this.components.elementAt(j)).updateUI();
                    validateTree();
                } catch (ClassNotFoundException cnfe) {
                    cnfe.printStackTrace();
                } catch (InstantiationException ie) {
                    ie.printStackTrace();
                } catch (IllegalAccessException iae) {
                    iae.printStackTrace();
                } catch (UnsupportedLookAndFeelException ulafe) {
                    ulafe.printStackTrace();
                }
                //System.err.println(m_tree.getCellRenderer());
                return;
            }
        }
    }

    private static void add(Container con, GridBagLayout g, GridBagConstraints c, Component co) {
	g.setConstraints(co, c);
	con.add(co);
    }

    public XPointerDemo(String tit, TXDocument root) {
        super(tit);
        m_doc = root;
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent e) {
                System.exit(0);
            }
        });
        
        m_alooks = UIManager.getInstalledLookAndFeels();
        JMenu jm = new JMenu("Look&Feel");
        this.components.addElement(jm);
        for (int i = 0;  i < m_alooks.length;  i ++) {
            JMenuItem mi = new JMenuItem(m_alooks[i].getName());
            this.components.addElement(mi);
            mi.addActionListener(this);
            jm.add(mi);
        }
        JMenuBar m_menubar = new JMenuBar();
        m_menubar.add(jm);
        this.components.addElement(m_menubar);
        setJMenuBar(m_menubar);

        m_text = new JTextField();
        m_text.addActionListener(this);
        this.components.addElement(m_text);

        m_button = new JButton("Go");
        m_button.addActionListener(this);
        this.components.addElement(m_button);

        m_scrollpane = new JScrollPane(m_tree = new JTree((TreeNode)root));
        this.components.addElement(m_scrollpane);
        this.components.addElement(m_tree);
        m_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);

        m_tree.addTreeSelectionListener(new TreeSelectionListener() {
            public void valueChanged(TreeSelectionEvent e) {
                if (!m_byuser) {
                    Child ch = (Child)(e.getPath().getLastPathComponent());
                    XPointer xp = ch.makeXPointer();
                    m_text.setText(xp == null ? "" : xp.toString());
                }
            }
        });

        JPanel m_panel = new JPanel();
        this.components.addElement(m_panel);
        GridBagLayout gbl = new GridBagLayout();
        m_panel.setLayout(gbl);
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.BOTH;
        gbc.weightx = 0.0;
        add(m_panel, gbl, gbc, new JLabel("XPointer: "));
        gbc.weightx = 1.0;
        add(m_panel, gbl, gbc, m_text);
        gbc.weightx = 0.0;
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        add(m_panel, gbl, gbc, m_button);

        this.getContentPane().add(m_panel, "North");
        this.getContentPane().add(m_scrollpane, "Center");
        int w = 400, h = 512;
        this.setSize(w, h);
        Dimension di = Toolkit.getDefaultToolkit().getScreenSize();
        this.setLocation((di.width-w)/2, (di.height-h)/2);
    }

    public static class MessageBox
        extends com.sun.java.swing.JDialog
        implements java.awt.event.ActionListener {

        JButton okbutton;

        public MessageBox(java.awt.Frame parent, String title, String message) {
            super(parent, title, true);

            Container cont = this.getContentPane();
            GridBagLayout gbl = new GridBagLayout();
            cont.setLayout(gbl);

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.fill = GridBagConstraints.BOTH;
            gbc.weightx = 1.0;
            gbc.weighty = 1.0;
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            JLabel label = new JLabel(message);
            XPointerDemo.add(cont, gbl, gbc, label);

            this.okbutton = new JButton("OK");
            this.okbutton.addActionListener(this);
            gbc.fill = GridBagConstraints.VERTICAL;
            gbc.weighty = 0.0;
            gbc.gridheight = GridBagConstraints.REMAINDER;
            XPointerDemo.add(cont, gbl, gbc, this.okbutton);

            Dimension dim = label.getPreferredSize();
            Dimension dim2 = this.okbutton.getPreferredSize();
            int w = dim.width+32;
            int h = dim.height+dim2.height+32;
            this.setSize(w, h);
            Dimension di = Toolkit.getDefaultToolkit().getScreenSize();
            this.setLocation((di.width-w)/2, (di.height-h)/2);
        }

        public void actionPerformed(java.awt.event.ActionEvent e) {
            if (e.getSource() == this.okbutton) {
                this.setVisible(false);
            }
        }
    }
}
