/*------------------------------------------------------------------------------------
Copyright (c)2000 TogetherSoft Corporation. Patents pending. All rights reserved.
------------------------------------------------------------------------------------*/

package com.togethersoft.modules.xmleditor.xmlcomponent;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import com.togethersoft.openapi.ide.message.*;
import com.togethersoft.openapi.ide.window.*;
import com.togethersoft.modules.xmleditor.xmltree.*;


public class XMLEditorComponent extends JPanel
{
  private XMLTreeManager  m_xmlTreeManager = null;

  private JTree            m_tree = null;
  private DefaultTreeModel m_treeModel;

  private JSplitPane  m_mainSplitPane = null;
  private JSplitPane  m_rightSplitPane = null;

  private DefaultMutableTreeNode m_selectedNode = null;

  //--------------------------------------------------------------------
  public XMLEditorComponent()
  {
    m_tree = new JTree ((TreeModel) null);
    m_tree.putClientProperty("JTree.lineStyle", "Angled");

    ToolTipManager.sharedInstance().registerComponent (m_tree);
    m_tree.setCellRenderer (new XMLTreeCellRenderer());

    m_tree.getSelectionModel().setSelectionMode (TreeSelectionModel.SINGLE_TREE_SELECTION);
    m_tree.addTreeSelectionListener (new TreeSelectionListener() {
       public void valueChanged (TreeSelectionEvent e)
       {
         DefaultMutableTreeNode node = (DefaultMutableTreeNode) m_tree.getLastSelectedPathComponent();
         nodeSelected (node);
       }
    });

    m_tree.addKeyListener (new KeyAdapter() {
       public void keyPressed (KeyEvent e)
       {
         int key = e.getKeyCode();
         if (key == KeyEvent.VK_DELETE)
         {
           DefaultMutableTreeNode node = (DefaultMutableTreeNode) m_tree.getLastSelectedPathComponent();
           deleteNode (node, true);
           return;
         }

         processKeyEvent2 (e);
       }
    });

    JScrollPane treeView = new JScrollPane (m_tree);

    m_rightSplitPane = new JSplitPane (JSplitPane.VERTICAL_SPLIT);
    m_mainSplitPane = new JSplitPane (JSplitPane.HORIZONTAL_SPLIT, treeView, m_rightSplitPane);

    setLayout (new BorderLayout());
    add (m_mainSplitPane, BorderLayout.CENTER);
  }

  //--------------------------------------------------------------------
  private void processKeyEvent2 (KeyEvent e)
  {
    processKeyEvent (e);
  }

  //--------------------------------------------------------------------
  public void setXMLTreeManager (XMLTreeManager xmlTreeManager)
  {
    m_xmlTreeManager = xmlTreeManager;
    m_selectedNode = null;

    DefaultMutableTreeNode rootNode = null;
    if (xmlTreeManager != null)
    {
      // create new tree model
      rootNode = createNode (m_xmlTreeManager.getRootElementInst());
      m_treeModel = new DefaultTreeModel (rootNode);
      m_tree.setModel (m_treeModel);
    }
    else
    {
      m_tree.setModel ((TreeModel) null);
    }

    m_mainSplitPane.setDividerLocation (0.40);
    selectNode (rootNode);
    repaint();
  }

  //--------------------------------------------------------------------
  public XMLTreeManager getXMLTreeManager()
  {
    return m_xmlTreeManager;
  }

  //--------------------------------------------------------------------
  public DefaultMutableTreeNode createNode (ElementInst elementInst)
  {
    NodeManager nodeManager = new NodeManager (this, elementInst);
    DefaultMutableTreeNode node = new DefaultMutableTreeNode (nodeManager);
    nodeManager.setTreeNode (node);

    // add child nodes
    Enumeration childElementEnum = elementInst.children();
    while (childElementEnum.hasMoreElements())
    {
      ElementInst childElementInst = (ElementInst) childElementEnum.nextElement();
      DefaultMutableTreeNode childNode = createNode (childElementInst);
      node.add (childNode);
    }

    return node;
  }

  //--------------------------------------------------------------------
  public void insertChildNode (DefaultMutableTreeNode parentNode, ElementInst childElementInst, int childIndex)
  {
    DefaultMutableTreeNode childNode = createNode (childElementInst);

    m_treeModel.insertNodeInto (childNode, parentNode, childIndex);
    selectNode (childNode);
  }

  //--------------------------------------------------------------------
  public void deleteNode (DefaultMutableTreeNode node, boolean askConfirm)
  {
    // get parent node; if it's null this node is the root,
    // therefore cannot be deleted

    DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) node.getParent();
    if (parentNode == null)
      return;

    NodeManager nodeManager = (NodeManager) node.getUserObject();
    ElementInst elementInst = nodeManager.getElementInst();

    if (askConfirm)
    {
		  String[] btns = {IdeButtonType.YES, IdeButtonType.NO};
		  String answer = IdeWindowManagerAccess.getWindowManager().showConfirmDialog(this, "Confirmation",
          "Element \'" + elementInst.getElementDef().getFullName() + "\' will be deleted.\nContinue?", btns);

      if (! IdeButtonType.YES.equals (answer))
        return;
    }


    // get new node to be selected after deleting this node

    DefaultMutableTreeNode newSelectedNode = node.getNextSibling();

    if (newSelectedNode == null)
      newSelectedNode = node.getPreviousSibling();

    if (newSelectedNode == null)
      newSelectedNode = parentNode;

    // delete from XMLTreeManager the element instance connected to this node
    NodeManager parentNodeManager = (NodeManager) parentNode.getUserObject();
    parentNodeManager.deleteChildElementInst (elementInst);

    // delete node from the TreeModel
    m_treeModel.removeNodeFromParent (node);

    // set new selected node
    selectNode (newSelectedNode);
  }

  //--------------------------------------------------------------------
  private void selectNode (DefaultMutableTreeNode node)
  {
    if (node != null)
    {
      TreePath nodePath = new TreePath (node.getPath());
      m_tree.setSelectionPath (nodePath);
      m_tree.scrollPathToVisible (nodePath);
    }
    else
    {
      m_rightSplitPane.setTopComponent (null);
      m_rightSplitPane.setBottomComponent (null);
    }
  }

  //--------------------------------------------------------------------
  private void nodeSelected (DefaultMutableTreeNode node)
  {
    NodeManager nodeManager;
    int availableHeight;

    if (m_selectedNode != null)
    {
      stopEditing();

      nodeManager = (NodeManager) m_selectedNode.getUserObject();
      availableHeight = m_rightSplitPane.getMaximumDividerLocation() +
              nodeManager.getButtonPane().getMinimumSize().height;

      nodeManager.dividerProportionalLocation =
           (double) m_rightSplitPane.getDividerLocation() / (double) availableHeight;
    }

    m_selectedNode = node;
    if (node == null)
      return;

    nodeManager = (NodeManager) node.getUserObject();

    InspectorPane inspectorPane = nodeManager.getInspectorPane();
    ElementButtonPane buttonPane = nodeManager.getButtonPane();

    // calculate position of the split dividor

    m_rightSplitPane.setTopComponent (inspectorPane);
    m_rightSplitPane.setBottomComponent (buttonPane);

    availableHeight = m_rightSplitPane.getMaximumDividerLocation() + buttonPane.getMinimumSize().height;

    if (nodeManager.dividerProportionalLocation >= 0)
    {
      int height1 = (int) (availableHeight * nodeManager.dividerProportionalLocation);
      m_rightSplitPane.setDividerLocation (height1);
    }
    else
    {
      int height1 = inspectorPane.getPreferredSize().height;
      int height2 = buttonPane.getPreferredSize().height;

      height1 = (availableHeight >= height1 + height2 || height2 < availableHeight/2)
                      ? availableHeight - height2 : availableHeight / 2;
      m_rightSplitPane.setDividerLocation (height1);
    }

    validate();
    repaint();
  }

  //--------------------------------------------------------------------
  public void stopEditing()
  {
    if (m_selectedNode != null)
      ((NodeManager) m_selectedNode.getUserObject()).stopEditing();
  }

  //--------------------------------------------------------------------
  public DefaultMutableTreeNode getSelectedNode()
  {
    return m_selectedNode;
  }

  //--------------------------------------------------------------------
  public NodeManager getSelectedNodeManager()
  {
    return (NodeManager) m_selectedNode.getUserObject();
  }

}
