//*****************************************************************************
/*
** FILE:   xm_NodeTypeRegistryDialog.java
**
** Copyright 1998 Steve Withall.
**
** HISTORY:
**    26Jul98  stevew  Created, based on df_DatabaseConnectDialog.
*/
package xm;

import eh.eh_Debug;

import com.sun.java.swing.table.AbstractTableModel;
import com.sun.java.swing.table.TableModel;

import com.sun.java.swing.Box;
import com.sun.java.swing.JButton;
import com.sun.java.swing.JDialog;
import com.sun.java.swing.JPanel;
import com.sun.java.swing.JScrollPane;
import com.sun.java.swing.JTabbedPane;
import com.sun.java.swing.JTable;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Point;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

//*****************************************************************************
/** <p>A dialog for displaying details about all the XML node types/names which
 *  are currently registered. It allows any value to be modified directly
 *  (except for the type/name of the entries), and allows new special entries
 *  to be added.</p>
 *
 *  <p>Note that all changes are purely transient, and will be lost once the
 *  application terminates.</p>
 */
public class xm_NodeTypeRegistryDialog extends JDialog
{
    /** The document model is currently not used (since the node type registry
     *  is global), but the registry may reorganised in future to allow
     *  different types to be registered for different documents. Since this
     *  attribute was present in the class upon which this was based, it is
     *  retained now to possibly save effort in restoring later. */
    xm_DocumentModel    TheDocumentModel  = null;

    Frame               ParentFrame       = null;

    /** Tabbed pane for the display of the two types of registry entries:
     *  standard types and special element names. */
    JTabbedPane         RegistryTabbedPane = null;

    // Attributes relating to the display of standard XML types.
    /** Panel for the display of the registered details of standard XML types. */
    JPanel              StandardTypesTab             = null;

    /** Panel for the display of the element's attributes. */
    JPanel              StandardTypesPanel           = null;

    /** Table displaying the element's attributes. */
    JTable              StandardTypesTable           = null;

    /** Model of the attribute data for display in the StandardTypesTable. */
    RegistryTableModel  StandardTypesTableModel      = null;

    /** Scroller for the table of attributes. */
    JScrollPane         StandardTypesTableScrollPane = null;

    // Attributes relating to the display of special XML element names.
    /** Panel for the display of the registered details of special XML element
     *  names. */
    JPanel              SpecialNamesTab             = null;

    /** Panel for the display of the element's attributes. */
    JPanel              SpecialNamesPanel           = null;

    /** Table displaying the element's attributes. */
    JTable              SpecialNamesTable           = null;

    /** Model of the attribute data for display in the SpecialNamesTable. */
    RegistryTableModel  SpecialNamesTableModel      = null;

    /** Scroller for the table of attributes. */
    JScrollPane         SpecialNamesTableScrollPane = null;

    // Buttons.
    JButton     AddButton   = new JButton("Add");
    JButton     CloseButton = new JButton("Close");

    //*****************************************************************************
    /** Constructor.
     */
    public xm_NodeTypeRegistryDialog(Frame             InputParentFrame,
                                     xm_DocumentModel  InputDocumentModel)
    {
	    super(InputParentFrame, "Registered XML element names/types", true);
	    ParentFrame      = InputParentFrame;
        TheDocumentModel = InputDocumentModel;
	    initScreen();
	}

    //*****************************************************************************
    /** Constructor.
     */
    public xm_NodeTypeRegistryDialog(Frame  InputParentFrame)
    {
	    super(InputParentFrame, "Registered XML element names/types", true);
	    ParentFrame = InputParentFrame;
	    initScreen();
	}

    //*****************************************************************************
    /** Initialise the screen.
     */
    protected void initScreen()
    {
	    // Load icon image.
//	    Image  IconImage = Toolkit.getDefaultToolkit().getImage("xm/images/xm_RegisteredTypesIcon.gif");
//	    InputParentFrame.setIconImage(IconImage);

        // Set up the tabbed pane where all the real work is done.
        RegistryTabbedPane = new JTabbedPane();
        RegistryTabbedPane.setBackground(Color.lightGray);
        addStandardTypesTab();
        addSpecialNamesTab();
    	getContentPane().add("Center", RegistryTabbedPane);

	    // Panel for buttons.
        Box  ButtonBox = Box.createHorizontalBox();
        ButtonBox.add(AddButton);
        ButtonBox.add(CloseButton);
    	AddButton.addActionListener(new AddButtonListener() );
    	CloseButton.addActionListener(new CloseButtonListener() );
    	getContentPane().add("South", ButtonBox);

        Point  ParentLocation = ParentFrame.getLocation();
        setBounds(ParentLocation.x + 30, ParentLocation.y + 50, 900, 550);
        show();
    }

    //*****************************************************************************
    /** Add 'Standard types' tab to display details about the standard XML types
     *  currently registered.
     */
    public void addStandardTypesTab()
    {
//	    eh_Debug.add(7, "xm_NodeTypeRegistryDialog.addStandardTypesTab:"); //TEMP
        StandardTypesTab = new JPanel();
        RegistryTabbedPane.addTab("Standard XML types", StandardTypesTab);
	    StandardTypesTab.setLayout(new BorderLayout());

        // Set up table for the standard types.
        StandardTypesTableModel = new RegistryTableModel(xm_NodeTypeRegistry.getTypeHashtable(),
                                                         false);
        StandardTypesTable = new JTable(StandardTypesTableModel);
        StandardTypesTable.setBackground(Color.lightGray);
        StandardTypesTableScrollPane = new JScrollPane(StandardTypesTable);
        StandardTypesTab.add(StandardTypesTableScrollPane, BorderLayout.CENTER);
    }

    //*****************************************************************************
    /** Add 'Special names' tab to display details about the special XML element
     *  names which are currently registered.
     */
    public void addSpecialNamesTab()
    {
//	    eh_Debug.add(7, "xm_NodeTypeRegistryDialog.addSpecialNamesTab:"); //TEMP
        SpecialNamesTab = new JPanel();
        RegistryTabbedPane.addTab("Special XML element names", SpecialNamesTab);
	    SpecialNamesTab.setLayout(new BorderLayout());

        // Set up table for the special types.
        SpecialNamesTableModel = new RegistryTableModel(xm_NodeTypeRegistry.getNameHashtable(),
                                                        true);
        SpecialNamesTable = new JTable(SpecialNamesTableModel);
        SpecialNamesTable.setBackground(Color.lightGray);
        SpecialNamesTableScrollPane = new JScrollPane(SpecialNamesTable);
        SpecialNamesTab.add(SpecialNamesTableScrollPane, BorderLayout.CENTER);
    }

    //*****************************************************************************
    /** Pass in the document model into which we are to place the analysed structure
     *  of the database.
     *
     *  @param  InputDocumentModel  The document model to represent the database's
     *                               structure
     */
    public void setDocumentModel(xm_DocumentModel  InputDocumentModel)
    {
        TheDocumentModel = InputDocumentModel;
    }

    //*****************************************************************************
    /** Retrieve the document model into which we placed the analysed structure
     *  of the database.
     *
     *  @return  The document model representing the database's structure
     */
    public xm_DocumentModel getDocumentModel()
    {
        return TheDocumentModel;
    }

    //*****************************************************************************
    // Button listener inner classes.
    //*****************************************************************************
    /** Handle pressing of the "Add" button. Allow a new registry entry to be
     *  entered.
     */
    class AddButtonListener implements ActionListener
    {
        public void actionPerformed(ActionEvent  InputEvent)
        {
            new xm_NodeTypeEditDialog(ParentFrame);

            //TBD Refresh the display to reflect new entry (if there was one).
        }
    }

    //*****************************************************************************
    /** Handle pressing of the "Close" button. Close this dialog, and do nothing
     *  else.
     */
    class CloseButtonListener implements ActionListener
    {
        public void actionPerformed(ActionEvent  InputEvent)
        {
            dispose();
        }
    }

    //*****************************************************************************
    /** Inner class to provide a model for the attributes for use in the table
     *  display.
     */
    class RegistryTableModel extends AbstractTableModel
    {
        /** Hashtable of node types managed by this model. */
        Hashtable  NodeTypeHashtable = null;

        /** Vector of node types managed by this model, to allow access to a node
         *  given its row number in the model. */
        Vector     NodeTypeVector    = new Vector();

        /** Flag to control whether the type or the name of each entry is to be
         *  displayed. */
        boolean    ShowNamesFlag     = false;

        //*****************************************************************************
        /** Constructor taking a Hashtable whose contents the model is to reflect,
         *  and a flag to control whether the type or the name of each entry is to
         *  be displayed.
         *
         *  @param  InputNodeTypeHashtable  Hashtable of node type definitions
         *  @param  InputShowNamesFlag      true means show each element's name (but
         *                                   not its type); false means vice versa
         */
        public RegistryTableModel(Hashtable  InputNodeTypeHashtable,
                                  boolean    InputShowNamesFlag)
        {
            NodeTypeHashtable = InputNodeTypeHashtable;
            ShowNamesFlag     = InputShowNamesFlag;

            // Set up vector of node types.
            xm_NodeTypeDefn  CurrentDefn         = null;
            Enumeration      RegistryEnumeration = InputNodeTypeHashtable.elements();
            while (RegistryEnumeration.hasMoreElements() )
            {
                CurrentDefn = (xm_NodeTypeDefn)RegistryEnumeration.nextElement();
                NodeTypeVector.addElement(CurrentDefn);
            }
        }

        //*****************************************************************************
        public int getColumnCount()
        {
            return 6;
        }

        //*****************************************************************************
        public int getRowCount()
        {
            return NodeTypeVector.size();
        }

        //*****************************************************************************
        public Object getValueAt(int InputRowNum, int InputColumnNum)
        {
            xm_NodeTypeDefn  CurrentDefn = (xm_NodeTypeDefn)NodeTypeVector.elementAt(InputRowNum);
            Object  CellValue = null;

            switch (InputColumnNum)
            {
                case 0:
                    if (ShowNamesFlag)
                        CellValue = CurrentDefn.getName();
                    else
                        CellValue = new Integer(CurrentDefn.getType());
                    break;

                case 1:
                    CellValue = CurrentDefn.getTypeString();
                    break;

                case 2:
                    CellValue = CurrentDefn.getNodeClassName();
                    break;

                case 3:
                    CellValue = CurrentDefn.getParserClassName();
                    break;

                case 4:
                    CellValue = CurrentDefn.getCustomizerClassName();
                    break;

                case 5:
                    CellValue = CurrentDefn.getViewClassName();
                    break;

                default:
                    CellValue = new String("*Unknown*");
	                eh_Debug.add(5, "xm_NodeTypeRegistryDialog.getValueAt: Invalid column number ("
	                                     + InputColumnNum + ") requested");
            }

            return CellValue;
        }

        //*****************************************************************************
        /** Get the name for the given column.
         *
         *  @param  InputColumnNum  the number of the column whose name is required
         */
        public String getColumnName(int InputColumnNum)
        {
            String  ColumnName = null;

            switch (InputColumnNum)
            {
                case 0:
                    if (ShowNamesFlag)
                        ColumnName = new String("Name");
                    else
                        ColumnName = new String("Type");
                    break;

                case 1:
                    ColumnName = new String("Description");
                    break;

                case 2:
                    ColumnName = new String("Node class");
                    break;

                case 3:
                    ColumnName = new String("Parser class");
                    break;

                case 4:
                    ColumnName = new String("Customizer class");
                    break;

                case 5:
                    ColumnName = new String("View class");
                    break;

                default:
                    ColumnName = new String("*Unknown*");
	                eh_Debug.add(5, "xm_NodeTypeRegistryDialog.getColumnName: Invalid column number ("
	                                     + InputColumnNum + ") requested");
            }

            return ColumnName;
        }

        //*****************************************************************************
//        public Class getColumnClass(int  InputColumnNum)
//        {
//            return getValueAt(0, InputColumnNum).getClass();
//        }

        //*****************************************************************************
        public boolean isCellEditable(int InputRowNum, int InputColumnNum)
        {
            // All but the first column can be edited.
            return (InputColumnNum != 0);
        }

        //*****************************************************************************
        public void setValueAt(Object InputValueObject, int InputRowNum, int InputColumnNum)
        {
	        eh_Debug.add(5, "xm_NodeTypeRegistryDialog.setValueAt: Set row "
	                              + InputRowNum + ", column "
	                              + InputColumnNum + " to " + InputValueObject.toString() );
            xm_NodeTypeDefn  CurrentDefn = (xm_NodeTypeDefn)NodeTypeVector.elementAt(InputRowNum);
            switch (InputColumnNum)
            {
//                case 0:
//                    if (ShowNamesFlag)
//                        CurrentDefn.setName(InputValueObject.toString());
//                    else
//                        CurrentDefn.setType(Integer.parseInt(InputValueObject.toString()));
//                    break;

                case 1:
                    CurrentDefn.setTypeString(InputValueObject.toString());  // Description
                    break;

                case 2:
                    //TBD First check that this is a valid class name. Ditto for
                    //TBD the other class names below.
                    CurrentDefn.setNodeClassName(InputValueObject.toString());
                    break;

                case 3:
                    CurrentDefn.setParserClassName(InputValueObject.toString());
                    break;

                case 4:
                    CurrentDefn.setCustomizerClassName(InputValueObject.toString());
                    break;

                case 5:
                    CurrentDefn.setViewClassName(InputValueObject.toString());
                    break;

                default:
	                eh_Debug.add(5, "xc_ElementCustomizer.setValueAt: Invalid column number ("
	                                     + InputColumnNum + ") requested");
            }
        }
    }
}
//*****************************************************************************
