package com.dbxml.db.admin.xmleditor;

/*
 * dbXML - Native XML Database
 * Copyright (C) 1999-2004  The dbXML Group, L.L.C.
 *
 * This program 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 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Id: XMLEditor.java,v 1.2 2004/02/12 00:17:55 bradford Exp $
 */

import java.awt.*;
import java.util.HashSet;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.Border;

import org.w3c.dom.Node;

import com.dbxml.db.admin.swing.NestedBorder;

/**
 * XMLEditor
 */

public class XMLEditor extends JScrollPane {
   static final Border InnerBorder = new NestedBorder(Color.white, Color.lightGray);
   static final Border LeftBorder = new NestedBorder(Color.white, Color.lightGray, false, true);
   static final Border TopBorder = new NestedBorder(Color.white, Color.lightGray, true, false);

   static final ImageIcon ImgAttrib = new ImageIcon(XMLEditor.class.getResource("attrib.gif"));
   static final ImageIcon ImgText = new ImageIcon(XMLEditor.class.getResource("text.gif"));
   static final ImageIcon ImgExpand = new ImageIcon(XMLEditor.class.getResource("expand.gif"));
   static final ImageIcon ImgNoExpand = new ImageIcon(XMLEditor.class.getResource("noexpand.gif"));
   static final ImageIcon ImgCollapse = new ImageIcon(XMLEditor.class.getResource("collapse.gif"));
   static final ImageIcon ImgCommentStart = new ImageIcon(XMLEditor.class.getResource("comment-start.gif"));
   static final ImageIcon ImgCommentEnd = new ImageIcon(XMLEditor.class.getResource("comment-end.gif"));

   DefaultNodeEditor rootEdit = new DefaultNodeEditor(this);
   JPanel rootPanel = new JPanel();
   JPanel rootMargin = new JPanel();
   HashSet nodeExpanded = new HashSet();
   boolean readOnly;
   boolean modified;
   boolean showAttribs;
   boolean showComments = true;
   boolean showRootElement = true;
   boolean collapseText = true;
   boolean expandable = true;
   int indentSize = 40;
   int attribLabelSize = 150;
   Font font = getFont();
   Color attribColor = Color.yellow;
   Color textColor = Color.white;
   Color commentColor = Color.cyan;
   ElementResourceMap resourceMap = new ElementResourceMap();
   ElementContentModel contentModel;
   SourceCallback source;
   Border outerBorder = BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(0, indentSize, 0, 0), InnerBorder);
   String space = " ";
   String attribStart = " ";
   String attribEnd = "";

   public XMLEditor() {
      super();

      rootPanel.setAutoscrolls(true);
      rootPanel.setOpaque(false);
      rootPanel.setLayout(new BorderLayout());
      rootPanel.add(rootEdit, BorderLayout.NORTH);
      rootPanel.setEnabled(false);

      rootMargin.setAutoscrolls(true);
      rootMargin.setMinimumSize(new Dimension(2, 2));
      rootMargin.setOpaque(false);
      rootMargin.setBorder(TopBorder);
      rootMargin.setEnabled(false);
      rootPanel.add(rootMargin, BorderLayout.CENTER);

      setViewportView(rootPanel);
   }

   public void setNode(Node node) {
      FontMetrics fm = getFontMetrics(getFont());
      int width = fm.getWidths()['A'];
      int height = fm.getHeight() + 2; // Border Height
      getVerticalScrollBar().setUnitIncrement(height);
      getHorizontalScrollBar().setUnitIncrement(width);

      rootMargin.setVisible(true);
      nodeExpanded.clear();
      rootEdit.setNode(node);
      modified = false;
   }

   public void setSource(SourceCallback source) {
      this.source = source;
   }

   public void setElementColor(Color elemColor) {
      rootEdit.setBackground(elemColor);
   }

   public Color getElementColor() {
      return rootEdit.getBackground();
   }

   public Color getAttribColor() {
      return attribColor;
   }

   public void setAttribColor(Color attribColor) {
      this.attribColor = attribColor;
      reconstruct();
   }

   public Color getTextColor() {
      return textColor;
   }

   public void setTextColor(Color textColor) {
      this.textColor = textColor;
      reconstruct();
   }

   public void setContentModel(ElementContentModel contentModel) {
      this.contentModel = contentModel;
   }

   public ElementContentModel getContentModel() {
      return contentModel;
   }

   public void setResourceMap(ElementResourceMap resourceMap) {
      this.resourceMap = resourceMap;
   }

   public ElementResourceMap getResourceMap() {
      return resourceMap;
   }

   public Color getCommentColor() {
      return commentColor;
   }

   public void setCommentColor(Color commentColor) {
      this.commentColor = commentColor;
      reconstruct();
   }

   public void setFont(Font font) {
      super.setFont(font);
      this.font = font;
   }

   public Font getFont() {
      return font;
   }

   public Node getNode() {
      return rootEdit.node;
   }

   public boolean isExpanded() {
      return rootEdit.expanded;
   }

   public void setReadOnly(boolean readOnly) {
      this.readOnly = readOnly;
      reconstruct();
   }

   public boolean isReadOnly() {
      return readOnly;
   }

   public void setShowRootElement(boolean showRootElement) {
      this.showRootElement = showRootElement;
      reconstruct();
   }

   public boolean isShowRootElement() {
      return showRootElement;
   }

   public void setShowComments(boolean showComments) {
      this.showComments = showComments;
      reconstruct();
   }

   public boolean isShowComments() {
      return showComments;
   }

   public void setCollapseText(boolean collapseText) {
      this.collapseText = collapseText;
      reconstruct();
   }

   public boolean isCollapseText() {
      return collapseText;
   }

   public void setIndentSize(int indentSize) {
      this.indentSize = indentSize;
      outerBorder = BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(0, indentSize, 0, 0), InnerBorder);
      rootEdit.setShowBorder(rootEdit.isShowBorder());
      reconstruct();
   }

   public int getIndentSize() {
      return indentSize;
   }

   public void setAttribLabelSize(int attribLabelSize) {
      this.attribLabelSize = attribLabelSize;
      reconstruct();
   }

   public int getAttribLabelSize() {
      return attribLabelSize;
   }

   public void setShowAttribs(boolean showAttribs) {
      this.showAttribs = showAttribs;
      reconstruct();
   }

   public boolean isShowAttribs() {
      return showAttribs;
   }

   public void setExpanded(boolean expanded) {
      rootEdit.setExpanded(expanded);
      getVerticalScrollBar().setValue(0);
      getHorizontalScrollBar().setValue(0);
   }

   public boolean isExpandable() {
      return expandable;
   }

   public void setExpandable(boolean expandable) {
      this.expandable = expandable;
      if ( !expandable && !rootEdit.expanded )
         rootEdit.setExpanded(true);
   }

   public boolean isModified() {
      return modified;
   }

   public void setModified(boolean modified) {
      this.modified = modified;
   }

   private void reconstruct() {
      Node node = rootEdit.node;
      if ( node != null ) {
         getVerticalScrollBar().setValue(0);
         getHorizontalScrollBar().setValue(0);
         rootEdit.setNode(node);
      }
   }

   boolean isNodeExpanded(Node node) {
      return nodeExpanded.contains(node);
   }
}
