/*
 * Copyright (C) 2005 - 2007 JasperSoft Corporation.  All rights reserved. 
 * http://www.jaspersoft.com.
 *
 * Unless you have purchased a commercial license agreement from JasperSoft,
 * the following license terms apply:
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 *
 * This program is distributed WITHOUT ANY WARRANTY; and without 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, see http://www.gnu.org/licenses/gpl.txt
 * or write to:
 *
 * Free Software Foundation, Inc.,
 * 59 Temple Place - Suite 330,
 * Boston, MA  USA  02111-1307
 *
 *
 *
 *
 * DocumentStructurePanel.java
 * 
 * Created on 25 novembre 2005, 11.34
 *
 */

package it.businesslogic.ireport.gui.documentstructure;
import it.businesslogic.ireport.ElementGroup;
import it.businesslogic.ireport.gui.MainFrame;
import it.businesslogic.ireport.gui.event.ReportBandChangedEvent;
import it.businesslogic.ireport.gui.event.ReportListener;
import it.businesslogic.ireport.gui.event.SubDatasetObjectChangedListener;
import it.businesslogic.ireport.util.LanguageChangedListener;
import it.businesslogic.ireport.util.Misc;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeSelectionModel;
import it.businesslogic.ireport.gui.*;
import it.businesslogic.ireport.*;
import it.businesslogic.ireport.gui.event.*;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import it.businesslogic.ireport.chart.gui.*;
import it.businesslogic.ireport.gui.docking.GenericDragTargetListener;
import it.businesslogic.ireport.undo.UnGroupEmentsOperation;
import java.awt.dnd.DropTarget;
import java.util.ArrayList;
import java.util.List;
import it.businesslogic.ireport.util.I18n;
import it.businesslogic.ireport.util.LanguageChangedEvent;
/**
 *
 * @author  Administrator
 */
public class DocumentStructurePanel extends javax.swing.JPanel implements ReportListener, SubDatasetObjectChangedListener, it.businesslogic.ireport.util.LanguageChangedListener {

    private boolean dontHandleEvent = false;

    private JReportFrame oldJReportFrame = null;

    /** Creates new form DocumentStructurePanel */
    public DocumentStructurePanel() {
        initComponents();

        DefaultTreeSelectionModel dtsm = (DefaultTreeSelectionModel)jTreeDocument.getSelectionModel();
        dtsm.setSelectionMode( DefaultTreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION );

        jTreeDocument.setDropTarget(new DropTarget(this, new GenericDragTargetListener()));

        //Modified by Felix Firgau for I18n on Feb 9th 2006
        DocumentStructureTreeNode rootDoc = new DocumentStructureTreeNode(it.businesslogic.ireport.util.I18n.getString("document","Document"));
        //End

        javax.swing.tree.DefaultTreeModel modelDoc = new javax.swing.tree.DefaultTreeModel(rootDoc);

        jTreeDocument.setModel( modelDoc );
        jTreeDocument.setCellRenderer( new DocumentStructureTreeCellRenderer());
        
        //I18n.addOnLanguageChangedListener( this );
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    private void initComponents() {
        jPopupMenuDocumentStructure = new javax.swing.JPopupMenu();
        jMenuItemDS_properties = new javax.swing.JMenuItem();
        jMenuItemDS_chartProperties = new javax.swing.JMenuItem();
        jSeparator22 = new javax.swing.JSeparator();
        jMenuItemMoveUp = new javax.swing.JMenuItem();
        jMenuItemMoveDown = new javax.swing.JMenuItem();
        jSeparator23 = new javax.swing.JSeparator();
        jMenuItemDS_cut = new javax.swing.JMenuItem();
        jMenuItemDS_copy = new javax.swing.JMenuItem();
        jMenuItemDS_paste = new javax.swing.JMenuItem();
        jMenuItemDS_delete = new javax.swing.JMenuItem();
        jPopupMenuDocumentStructureBand = new javax.swing.JPopupMenu();
        jMenuItemDSB_properties = new javax.swing.JMenuItem();
        jPopupMenuDocumentStructureGroup = new javax.swing.JPopupMenu();
        jMenuItemUngroup = new javax.swing.JMenuItem();
        jScrollPane2 = new javax.swing.JScrollPane();
        jTreeDocument = new javax.swing.JTree();

        jMenuItemDS_properties.setText("Properties");
        jMenuItemDS_properties.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemDS_propertiesActionPerformed(evt);
            }
        });

        jPopupMenuDocumentStructure.add(jMenuItemDS_properties);

        jMenuItemDS_chartProperties.setIcon(new javax.swing.ImageIcon(""));
        jMenuItemDS_chartProperties.setText("Chart properties");
        jMenuItemDS_chartProperties.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemDS_chartPropertiesActionPerformed(evt);
            }
        });

        jPopupMenuDocumentStructure.add(jMenuItemDS_chartProperties);

        jPopupMenuDocumentStructure.add(jSeparator22);

        jMenuItemMoveUp.setText("Move up");
        jMenuItemMoveUp.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemMoveUpActionPerformed(evt);
            }
        });

        jPopupMenuDocumentStructure.add(jMenuItemMoveUp);

        jMenuItemMoveDown.setText("Move down");
        jMenuItemMoveDown.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemMoveDownActionPerformed(evt);
            }
        });

        jPopupMenuDocumentStructure.add(jMenuItemMoveDown);

        jPopupMenuDocumentStructure.add(jSeparator23);

        jMenuItemDS_cut.setIcon(new javax.swing.ImageIcon(getClass().getResource("/it/businesslogic/ireport/icons/menu/cut.png")));
        jMenuItemDS_cut.setText("Cut");
        jMenuItemDS_cut.setEnabled(false);
        jMenuItemDS_cut.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemDS_cutActionPerformed(evt);
            }
        });

        jPopupMenuDocumentStructure.add(jMenuItemDS_cut);

        jMenuItemDS_copy.setIcon(new javax.swing.ImageIcon(getClass().getResource("/it/businesslogic/ireport/icons/menu/copy.png")));
        jMenuItemDS_copy.setText("Copy");
        jMenuItemDS_copy.setEnabled(false);
        jMenuItemDS_copy.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemDS_copyActionPerformed(evt);
            }
        });

        jPopupMenuDocumentStructure.add(jMenuItemDS_copy);

        jMenuItemDS_paste.setIcon(new javax.swing.ImageIcon(getClass().getResource("/it/businesslogic/ireport/icons/menu/paste.png")));
        jMenuItemDS_paste.setText("Paste");
        jMenuItemDS_paste.setEnabled(false);
        jMenuItemDS_paste.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemDS_pasteActionPerformed(evt);
            }
        });

        jPopupMenuDocumentStructure.add(jMenuItemDS_paste);

        jMenuItemDS_delete.setIcon(new javax.swing.ImageIcon(getClass().getResource("/it/businesslogic/ireport/icons/menu/delete.png")));
        jMenuItemDS_delete.setText("Delete");
        jMenuItemDS_delete.setEnabled(false);
        jMenuItemDS_delete.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemDS_deleteActionPerformed(evt);
            }
        });

        jPopupMenuDocumentStructure.add(jMenuItemDS_delete);

        jMenuItemDSB_properties.setText("Band properties");
        jMenuItemDSB_properties.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemDSB_propertiesActionPerformed(evt);
            }
        });

        jPopupMenuDocumentStructureBand.add(jMenuItemDSB_properties);

        jMenuItemUngroup.setText("Ungroup");
        jMenuItemUngroup.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemUngroupActionPerformed(evt);
            }
        });

        jPopupMenuDocumentStructureGroup.add(jMenuItemUngroup);

        setLayout(new java.awt.BorderLayout());

        jTreeDocument.addTreeExpansionListener(new javax.swing.event.TreeExpansionListener() {
            public void treeCollapsed(javax.swing.event.TreeExpansionEvent evt) {
                jTreeDocumentTreeCollapsed(evt);
            }
            public void treeExpanded(javax.swing.event.TreeExpansionEvent evt) {
                jTreeDocumentTreeExpanded(evt);
            }
        });
        jTreeDocument.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
            public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
                jTreeDocumentValueChanged(evt);
            }
        });
        jTreeDocument.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                jTreeDocumentMousePressed(evt);
            }
        });

        jScrollPane2.setViewportView(jTreeDocument);

        add(jScrollPane2, java.awt.BorderLayout.CENTER);
        //Added by Felix Firgau for I18n on Feb 9th 2006
        I18n.addOnLanguageChangedListener( this );//End

    }// </editor-fold>//GEN-END:initComponents

    private void jMenuItemUngroupActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemUngroupActionPerformed

        if (jTreeDocument.getSelectionCount() > 0) {
            DocumentStructureTreeNode elementNode = (DocumentStructureTreeNode)jTreeDocument.getSelectionPath().getLastPathComponent();
            if (elementNode.getUserObject() instanceof ElementGroup) {
                String elementGroupName = ((ElementGroup)elementNode.getUserObject()).getName();
                while ( ((DocumentStructureTreeNode)elementNode.getParent()).getUserObject() instanceof ElementGroup)
                {
                    elementNode = (DocumentStructureTreeNode)elementNode.getParent();
                    elementGroupName = ((ElementGroup)elementNode.getUserObject()).getName() + "." + elementGroupName;
                }

                String newElementGroupName = elementGroupName;
                if (newElementGroupName.lastIndexOf(".")>=0)
                {
                    newElementGroupName = newElementGroupName.substring(0,newElementGroupName.lastIndexOf("."));
                }
                else
                {
                    newElementGroupName = "";
                }

                /************************/
                UnGroupEmentsOperation undoOp = new UnGroupEmentsOperation(MainFrame.getMainInstance().getActiveReportFrame());
                Vector elements = MainFrame.getMainInstance().getActiveReportFrame().getReport().getElements();
                for (int i=0; i<elements.size(); ++i)
                {
                    ReportElement element = (ReportElement)elements.elementAt(i);
                    String oldElementGroupName = element.getElementGroup();
                    if (element.getElementGroup().startsWith(elementGroupName+".") || element.getElementGroup().equals(elementGroupName))
                    {
                         String tmpElementGroupName = element.getElementGroup().substring(elementGroupName.length());
                         if (tmpElementGroupName.length() == 0) tmpElementGroupName = newElementGroupName;
                         tmpElementGroupName = newElementGroupName + tmpElementGroupName;
                         if (tmpElementGroupName.startsWith(".")) tmpElementGroupName = tmpElementGroupName.substring(1);

                        element.setElementGroup(tmpElementGroupName);
                        undoOp.addElement(element, i,i, oldElementGroupName, tmpElementGroupName);
                    }
                }

                MainFrame.getMainInstance().getActiveReportFrame().addUndoOperation(undoOp);

                MainFrame.getMainInstance().getActiveReportFrame().fireReportListenerReportElementsChanged(new ReportElementChangedEvent(MainFrame.getMainInstance().getActiveReportFrame(), new Vector() , ReportElementChangedEvent.REMOVED ));
            }
        }
        // Get group name...


    }//GEN-LAST:event_jMenuItemUngroupActionPerformed

    private void jTreeDocumentTreeCollapsed(javax.swing.event.TreeExpansionEvent evt) {//GEN-FIRST:event_jTreeDocumentTreeCollapsed
           //System.out.println("collapsing..." + evt.getPath());
    }//GEN-LAST:event_jTreeDocumentTreeCollapsed

    private void jTreeDocumentTreeExpanded(javax.swing.event.TreeExpansionEvent evt) {//GEN-FIRST:event_jTreeDocumentTreeExpanded
           // System.out.println("expanding..." + evt.getPath());


    }//GEN-LAST:event_jTreeDocumentTreeExpanded

    private void jMenuItemDSB_propertiesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemDSB_propertiesActionPerformed
if (jTreeDocument.getSelectionCount() > 0) {
            DocumentStructureTreeNode elementNode = (DocumentStructureTreeNode)jTreeDocument.getSelectionPath().getLastPathComponent();
            if (elementNode.getUserObject() instanceof Band) {
                String thisBand = ((Band)elementNode.getUserObject()).getName();
                MainFrame.getMainInstance().jMenuItemBandsActionPerformed(evt);
                MainFrame.getMainInstance().getBandsDialog().setSelectedBand( thisBand );
            }
        }
    }//GEN-LAST:event_jMenuItemDSB_propertiesActionPerformed

    private void jMenuItemDS_deleteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemDS_deleteActionPerformed
MainFrame.getMainInstance().getActiveReportFrame().deleteSelectedElements();
    }//GEN-LAST:event_jMenuItemDS_deleteActionPerformed

    private void jMenuItemDS_pasteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemDS_pasteActionPerformed
MainFrame.getMainInstance().getActiveReportFrame().paste();
    }//GEN-LAST:event_jMenuItemDS_pasteActionPerformed

    private void jMenuItemDS_copyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemDS_copyActionPerformed
MainFrame.getMainInstance().getActiveReportFrame().copy();
    }//GEN-LAST:event_jMenuItemDS_copyActionPerformed

    private void jMenuItemDS_cutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemDS_cutActionPerformed
MainFrame.getMainInstance().getActiveReportFrame().cut();
    }//GEN-LAST:event_jMenuItemDS_cutActionPerformed

    private void jMenuItemMoveDownActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemMoveDownActionPerformed
if (MainFrame.getMainInstance().getActiveReportFrame() != null) {
            JReportFrame jrf = MainFrame.getMainInstance().getActiveReportFrame();
            jrf.moveDown();

            if (jrf.getSelectedElements().size()>0)
                updateDocumentStructureTree(jrf);

        }
    }//GEN-LAST:event_jMenuItemMoveDownActionPerformed

    private void jMenuItemMoveUpActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemMoveUpActionPerformed
 if (MainFrame.getMainInstance().getActiveReportFrame() != null) {
         JReportFrame jrf = MainFrame.getMainInstance().getActiveReportFrame();
         jrf.moveUp();
         this.jTreeDocument.updateUI();
         printSelectedPaths("Prima");
         if (jrf.getSelectedElements().size()>0)
             updateDocumentStructureTree(jrf);

         printSelectedPaths("Dopo");

        }

    }//GEN-LAST:event_jMenuItemMoveUpActionPerformed

    private void jMenuItemDS_chartPropertiesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemDS_chartPropertiesActionPerformed
 if (MainFrame.getMainInstance().getActiveReportFrame() != null) {
                JReportFrame jrf = MainFrame.getMainInstance().getActiveReportFrame();
                if (jTreeDocument.getSelectionCount() > 0) {
                    DocumentStructureTreeNode elementNode = (DocumentStructureTreeNode)jTreeDocument.getSelectionPath().getLastPathComponent();
                    if (elementNode.getUserObject() instanceof ChartReportElement2 )
                    {
                        ChartPropertiesDialog cpd = new ChartPropertiesDialog(MainFrame.getMainInstance(),true);
                        cpd.setChartElement( (ChartReportElement2)elementNode.getUserObject());
                        cpd.setVisible(true);
                    }

                }
        }
    }//GEN-LAST:event_jMenuItemDS_chartPropertiesActionPerformed

    public void languageChanged(LanguageChangedEvent evt) {

    this.applyI18n();
}


    private void jMenuItemDS_propertiesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemDS_propertiesActionPerformed
      MainFrame.getMainInstance().getElementPropertiesDialog().setVisible(true);
      MainFrame.getMainInstance().getElementPropertiesDialog().updateSelection();
    }//GEN-LAST:event_jMenuItemDS_propertiesActionPerformed

    private void jTreeDocumentValueChanged(javax.swing.event.TreeSelectionEvent evt) {//GEN-FIRST:event_jTreeDocumentValueChanged
          if (isDontHandleEvent()) return;

          
                // Get active jrf...
                if (MainFrame.getMainInstance().getActiveReportFrame() != null) {
                    //dontHandleEvent = true;
                    try {
                        JReportFrame jrf = MainFrame.getMainInstance().getActiveReportFrame();
                        Vector elementsToSelect = new Vector();
                        Vector bandsToSelect = new Vector();

                        TreePath[] path = jTreeDocument.getSelectionPaths();

                        //jrf.setSelectedBands(new Vector());
                        
                        for (int i=0; i<path.length; ++i)
                        {
                            DocumentStructureTreeNode elementNode = (DocumentStructureTreeNode)path[i].getLastPathComponent();
                            if (elementNode.getUserObject() instanceof Band) {
                                bandsToSelect.addElement( (Band)elementNode.getUserObject());
                            }
                        }
                                               
                        for (int i=0; i<path.length; ++i) {
                            DocumentStructureTreeNode elementNode = (DocumentStructureTreeNode)path[i].getLastPathComponent();
                            if (elementNode.getUserObject() instanceof ReportElement) {
                                elementsToSelect.addElement( (ReportElement)elementNode.getUserObject());
                            }
                            //else if (elementNode.getUserObject() instanceof Band)
                            //{
                            //    bandsToSelect.addElement( (Band)elementNode.getUserObject());
                            //}
                            else if (path.length == 1) {
                                
                                jrf.setSelectedBands(bandsToSelect);
                                jrf.setSelectedElement(null);
                                
                                //if (elementNode.getUserObject() instanceof Band)
                                //{
                                //    Vector selectedBands = new Vector();
                                //    selectedBands.add(elementNode.getUserObject());
                                //    jrf.setSelectedBands(selectedBands);
                                //}
                                return;
                            }
                            else if (elementNode.getUserObject() instanceof ElementGroup)
                            {
                                jrf.setSelectedBands(bandsToSelect);
                                jrf.setSelectedElement(null);
                                return;
                            }
                        }
  
                        jrf.getSelectedElements().clear();
                        Enumeration e = elementsToSelect.elements();
                        while (e.hasMoreElements()) {
                            jrf.addSelectedElement((ReportElement)e.nextElement(), false);
                        }
                        
                        if (elementsToSelect.size() > 0)
                        {
                            jrf.setSelectedBands(new Vector());
                        }
                        else
                        {
                            jrf.setSelectedBands(bandsToSelect);
                        }
                        
                        
                        jrf.fireSelectionChangedEvent();
                    } catch (Exception ex)
                    {}
                    //
                }
    }//GEN-LAST:event_jTreeDocumentValueChanged

    private void jTreeDocumentMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jTreeDocumentMousePressed
 if (evt.getButton() == evt.BUTTON3) {
            if (MainFrame.getMainInstance().getActiveReportFrame() != null) {
                JReportFrame jrf = MainFrame.getMainInstance().getActiveReportFrame();
                Misc.ensurePathIsSelected(jTreeDocument.getPathForLocation(evt.getX(), evt.getY() ), jTreeDocument);
                //jTreeDocument.setSelectionPath( jTreeDocument.getPathForLocation(evt.getX(), evt.getY() ) );
                if (jTreeDocument.getSelectionCount() > 0) {
                    DocumentStructureTreeNode elementNode = (DocumentStructureTreeNode)jTreeDocument.getSelectionPath().getLastPathComponent();
                    if (elementNode.getUserObject() instanceof ReportElement) {
                        // (ReportElement)elementNode.getUserObject());
                        jMenuItemDS_chartProperties.setVisible( elementNode.getUserObject() instanceof ChartReportElement2  );
                        this.jPopupMenuDocumentStructure.show(jTreeDocument, evt.getPoint().x, evt.getPoint().y);

                    } else if (elementNode.getUserObject() instanceof Band) {
                        // (ReportElement)elementNode.getUserObject());
                        this.jPopupMenuDocumentStructureBand.show(jTreeDocument, evt.getPoint().x, evt.getPoint().y);

                    } else if (elementNode.getUserObject() instanceof ElementGroup) {
                        // (ReportElement)elementNode.getUserObject());
                        this.jPopupMenuDocumentStructureGroup.show(jTreeDocument, evt.getPoint().x, evt.getPoint().y);

                    }
                }
            }

        }
        else if (evt.getButton() == evt.BUTTON1 && evt.getClickCount() == 2) {

            if (MainFrame.getMainInstance().getActiveReportFrame() != null) {

                JReportFrame jrf = MainFrame.getMainInstance().getActiveReportFrame();
                if (jrf.getSelectedElements().size() > 0) {
                    MainFrame.getMainInstance().getElementPropertiesDialog().setVisible(true);
                    //MainFrame.getMainInstance().getElementPropertiesDialog().updateSelection();
                }
            }
        }
    }//GEN-LAST:event_jTreeDocumentMousePressed

    public void printSelectedPaths(String prefix)
    {
        try {
                       Enumeration enum_extended_paths = jTreeDocument.getExpandedDescendants(new TreePath(new Object[]{ jTreeDocument.getModel().getRoot() }));
                       if (enum_extended_paths != null)
                       {
                                  while (enum_extended_paths.hasMoreElements())
                                  {
                                   TreePath path = (TreePath)enum_extended_paths.nextElement();
                                   //System.out.println(prefix+ " "+path);
                               }
                       }
                } catch (Exception ex)
                {
                    ex.printStackTrace();
                }
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem jMenuItemDSB_properties;
    private javax.swing.JMenuItem jMenuItemDS_chartProperties;
    private javax.swing.JMenuItem jMenuItemDS_copy;
    private javax.swing.JMenuItem jMenuItemDS_cut;
    private javax.swing.JMenuItem jMenuItemDS_delete;
    private javax.swing.JMenuItem jMenuItemDS_paste;
    private javax.swing.JMenuItem jMenuItemDS_properties;
    private javax.swing.JMenuItem jMenuItemMoveDown;
    private javax.swing.JMenuItem jMenuItemMoveUp;
    private javax.swing.JMenuItem jMenuItemUngroup;
    private javax.swing.JPopupMenu jPopupMenuDocumentStructure;
    private javax.swing.JPopupMenu jPopupMenuDocumentStructureBand;
    private javax.swing.JPopupMenu jPopupMenuDocumentStructureGroup;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JSeparator jSeparator22;
    private javax.swing.JSeparator jSeparator23;
    private javax.swing.JTree jTreeDocument;
    // End of variables declaration//GEN-END:variables


    public void updateDocumentStructureTree(JReportFrame jrf)
    {
        List openedPaths = null;

        try {

                openedPaths = new ArrayList();
                Enumeration enum_extended_paths = jTreeDocument.getExpandedDescendants(new TreePath(new Object[]{ jTreeDocument.getModel().getRoot() }));
                if (enum_extended_paths!=null)
                {
                    while (enum_extended_paths.hasMoreElements())
                    {
                        TreePath path = (TreePath)enum_extended_paths.nextElement();
                        openedPaths.add( ((DocumentStructureTreeNode)path.getLastPathComponent()).getNodeId() );
                    }
                }
           } catch (Exception ex)
           {
                ex.printStackTrace();
           }

        if (jrf != oldJReportFrame)
        {
            if (oldJReportFrame != null) oldJReportFrame.setOpenedNodesDocumentStructure( openedPaths );
            if (jrf != null) openedPaths = jrf.getOpenedNodesDocumentStructure();
        }

        setDontHandleEvent(true);
        // Update the document tree structure...
        ((DocumentStructureTreeNode)this.jTreeDocument.getModel().getRoot()).removeAllChildren();
        ((javax.swing.tree.DefaultTreeModel)(this.jTreeDocument.getModel())).reload();

        if (jrf != null)
        {


            Enumeration bands = jrf.getReport().getBands().elements();
            while (bands.hasMoreElements())
            {
                Band band = (Band)bands.nextElement();
                DocumentStructureTreeNode bandNode = new DocumentStructureTreeNode(band);
                ((DocumentStructureTreeNode)this.jTreeDocument.getModel().getRoot()).add( bandNode);

                Enumeration elements = jrf.getReport().getElements().elements();
                while (elements.hasMoreElements())
                {
                    ReportElement element = (ReportElement)elements.nextElement();
                    if (element.getBand() == band)
                    {
                        String elementGroup = element.getElementGroup();
                        try {
                            if (element.getParentElement() != null)
                            {
                                DocumentStructureTreeNode parentNode = findElementTreeNode(element.getParentElement(),true);
                                if (parentNode != null)
                                {
                                    addElementToGroup(parentNode, elementGroup, element, openedPaths);
                                    if (openedPaths != null && openedPaths.contains(parentNode.getNodeId()))
                                    {
                                        this.expandPath(parentNode);
                                    }
                                }

                            }
                            else
                            {
                                addElementToGroup(bandNode, elementGroup, element, openedPaths);
                            }

                        } catch (Exception ex)
                        {
                            ex.printStackTrace();
                        }
                    }
                }
                if (openedPaths != null && openedPaths.contains(bandNode.getNodeId()))
                {
                    this.expandPath(bandNode);
                }
            }
            setDontHandleEvent(false);
            this.reportElementsSelectionChanged(new ReportElementsSelectionEvent(jrf,  jrf.getSelectedElements()));
        }

        oldJReportFrame = jrf;

        jTreeDocument.updateUI();
    }

    public void addElementToGroup(DocumentStructureTreeNode parentNode, String subGroup, ReportElement element, List openedPaths)
    {
        // 1. We have to find the group node...
        if (subGroup.equals(""))
        {
            DocumentStructureTreeNode newNode = new DocumentStructureTreeNode(element);
            parentNode.add( newNode);

            if (openedPaths != null && openedPaths.contains(newNode.getNodeId()))
            {
                expandPath( (DocumentStructureTreeNode)newNode);
            }

            return;
        }
        String levelGroupName = "";
        if (subGroup.indexOf(".")>=0)
        {
            levelGroupName = subGroup.substring(0, subGroup.indexOf("."));
            subGroup = subGroup.substring(subGroup.indexOf(".")+1);
        }
        else
        {
            levelGroupName = subGroup;
            subGroup = "";
        }

        // 2. Look for the node named levelGroupName
        for (int i =0; i<parentNode.getChildCount(); ++i)
        {
            DocumentStructureTreeNode dmtn = (DocumentStructureTreeNode)parentNode.getChildAt(i);
            if (dmtn.getUserObject() != null && dmtn.getUserObject() instanceof ElementGroup)
            {
                ElementGroup ge = (ElementGroup)dmtn.getUserObject();
                if (ge.getName().equals( levelGroupName ))
                {
                    addElementToGroup(dmtn, subGroup, element, openedPaths);
                    return;
                }
            }
        }

        // Node doesn't exists....
        DocumentStructureTreeNode dmtn = new DocumentStructureTreeNode(new ElementGroup(levelGroupName));
        parentNode.add( dmtn );
        addElementToGroup(dmtn, subGroup, element, openedPaths);

        if (openedPaths != null && openedPaths.contains(dmtn.getNodeId()))
        {
            expandPath( (DocumentStructureTreeNode)dmtn);
        }


    }

    public void expandPath(DocumentStructureTreeNode node)
    {
       //if (node.getChildCount() == 0) return;
        try {
            if (node.getParent() != null)
            {
                expandPath((DocumentStructureTreeNode)node.getParent());
            }
            jTreeDocument.expandPath(new TreePath(((DocumentStructureTreeNode)node).getPath() ));
        } catch (Exception ex)
        {
            ex.printStackTrace();
        }
     }


    public void reportBandChanged(ReportBandChangedEvent evt) {
        this.updateDocumentStructureTree( evt.getJReportFrame());
    }

    public void reportElementsChanged(ReportElementChangedEvent evt) {

        if (evt.getType() == ReportElementChangedEvent.CHANGED) {
            for (int ir=0; ir<evt.getElements().size(); ++ir)
            {
                ReportElement re = (ReportElement)evt.getElements().elementAt(ir);

                DocumentStructureTreeNode node = findElementTreeNode(re, true);
                if (node == null) {
                    // This node has changed your band....
                    // Find the node based on objects availables....
                    node = findElementTreeNode(re, false);
                    if (node == null) return; // This should not happen....
                    // Remove from your parent....
                    node.removeFromParent();
                    // Add to the new parent...
                    DocumentStructureTreeNode root = (DocumentStructureTreeNode)jTreeDocument.getModel().getRoot();
                    for (int i=0; i<root.getChildCount(); ++i) {
                        DocumentStructureTreeNode bandNode = (DocumentStructureTreeNode)root.getChildAt(i);
                        if (bandNode.getUserObject() == re.band) {
                            bandNode.add( node );
                            setDontHandleEvent(true);
                            if (evt.getJReportFrame().getSelectedElements().contains( re )) {
                                jTreeDocument.getSelectionModel().addSelectionPath(new TreePath(new Object[]
                                {root, bandNode,node}));
                            }
                            setDontHandleEvent(false);
                            break;
                        }
                    }
                }
            }
            jTreeDocument.updateUI();
        }
        else if (evt.getType() == ReportElementChangedEvent.REMOVED) {

            /*
            for (int i=0; i<evt.getElements().size(); ++i)
            {
                ReportElement re = (ReportElement)evt.getElements().elementAt(i);
                // find this element....
                DocumentStructureTreeNode node = findElementTreeNode(re,true);
                if (node != null) {
                    node.removeFromParent();
                }
            }
            */
            updateDocumentStructureTree( MainFrame.getMainInstance().getActiveReportFrame() );
            jTreeDocument.updateUI();
        }
        else if (evt.getType() == ReportElementChangedEvent.ADDED) {

            updateDocumentStructureTree( MainFrame.getMainInstance().getActiveReportFrame() );

            jTreeDocument.updateUI();
        }


    }//end reportElementsChanged



    public void reportElementsSelectionChanged(ReportElementsSelectionEvent evt) {

        if (evt.getCrosstabReportElement() != null) return;
        
        if (isDontHandleEvent()) return;
        setDontHandleEvent(true);

        // ((DocumentStructureTreeNode) path[0].getLastPathComponent()) == jTreeDocument.getModel().getRoot()
            
        TreePath[] path = jTreeDocument.getSelectionPaths();
        if (path != null && evt.getSelectedElements() != null && evt.getSelectedElements().size() == 0 &&
         ( ((DocumentStructureTreeNode) path[0].getLastPathComponent()).getUserObject() instanceof Band
            || ((DocumentStructureTreeNode) path[0].getLastPathComponent()).getUserObject() instanceof ElementGroup
            || ((DocumentStructureTreeNode) path[0].getLastPathComponent()) == jTreeDocument.getModel().getRoot()) )
        {   
                setDontHandleEvent(false);
                return;
        }

        jTreeDocument.getSelectionModel().clearSelection();


        java.util.Vector v = evt.getSelectedElements();
        Enumeration e = v.elements();
        while (e.hasMoreElements()) {
            ReportElement re = (ReportElement)e.nextElement();
            // looking for it in the tree...
            //1. Search the band...
            DocumentStructureTreeNode enode = findElementTreeNode( re, true);
            //TreePath treePath = findReportElement((DocumentStructureTreeNode)jTreeDocument.getModel().getRoot(), re);
            if (enode != null)
            {
                jTreeDocument.getSelectionModel().addSelectionPath(new TreePath(enode.getPath()));
            }

        }
        
        
        
        if (v.size() == 0)
        {
            v = MainFrame.getMainInstance().getActiveReportFrame().getSelectedBands();
            
            e = v.elements();
            while (e.hasMoreElements()) {
                Band band = (Band)e.nextElement();
                // looking for it in the tree...
                //1. Search the band...
                DocumentStructureTreeNode enode = findBandTreeNode( band );
                if (enode != null)
                {
                    jTreeDocument.getSelectionModel().addSelectionPath(new TreePath(enode.getPath()));
                }

            }
        }
        
        setDontHandleEvent(false);

    }

    /*
    private TreePath findReportElement(DocumentStructureTreeNode root, ReportElement re)
    {
            List nodes = new ArrayList();
            nodes.add(root);
            for (int i=0; i<root.getChildCount(); ++i) {
                DocumentStructureTreeNode bandNode = (DocumentStructureTreeNode)root.getChildAt(i);
                if (bandNode.getUserObject() == re.band) {
                    String elementGroup = re.getElementGroup();
                    nodes.add(bandNode);
                    while ( elementGroup.length() > 0)
                    {
                        String localGroup = "";
                        if (elementGroup.indexOf(".") > 0)
                        {
                            localGroup = elementGroup.substring(0, elementGroup.indexOf("."));
                            elementGroup = elementGroup.substring(elementGroup.indexOf(".")+1);
                        }
                        else
                        {
                            localGroup = elementGroup;
                            elementGroup = "";
                        }

                        boolean found = false;
                        for (int k=0; k<bandNode.getChildCount(); ++k)
                        {
                            DocumentStructureTreeNode childNode = (DocumentStructureTreeNode)bandNode.getChildAt(k);
                            if (childNode.getUserObject() instanceof ElementGroup &&
                                ((ElementGroup)childNode.getUserObject()).getName().equals(localGroup)) {

                                nodes.add( childNode );
                                bandNode = childNode;
                                found = true;
                                break;
                            }
                        }


                    }

                    for (int k=0; k<bandNode.getChildCount(); ++k) {
                        DocumentStructureTreeNode child = (DocumentStructureTreeNode)bandNode.getChildAt(k);
                        if (child.getUserObject() == re) {
                            nodes.add(child);

                            return new TreePath(nodes.toArray());
                        }
                    }
                }
            }
            return null;
    }
     */

    /**
     *     If searchInYourBandOnly == true
     *     This method Look for the userObject re in elements contained in the same band
     *     of the element. This method MUST CHECK that the report IS in the band
     *     assigned. If not it must return null. The reason is that if the element
     *     is not found in your band, it has changed the band attribute and must be updated.
     */
    public DocumentStructureTreeNode findElementTreeNode( ReportElement re, boolean searchInYourBandOnly) {
        // looking for it in the tree...
        //1. Search the band...
        DocumentStructureTreeNode root = (DocumentStructureTreeNode)jTreeDocument.getModel().getRoot();
        for (int i=0; i<root.getChildCount(); ++i) {
            DocumentStructureTreeNode bandNode = (DocumentStructureTreeNode)root.getChildAt(i);
            if (!searchInYourBandOnly || bandNode.getUserObject() == re.band) {

                DocumentStructureTreeNode newchild = findElementInTreeNode(bandNode,re);
                if (newchild != null) return newchild;
            }
        }
        return null;
    }
    
    public DocumentStructureTreeNode findBandTreeNode( Band band) {
        // looking for it in the tree...
        //1. Search the band...
        DocumentStructureTreeNode root = (DocumentStructureTreeNode)jTreeDocument.getModel().getRoot();
        for (int i=0; i<root.getChildCount(); ++i) {
            DocumentStructureTreeNode bandNode = (DocumentStructureTreeNode)root.getChildAt(i);
            if (bandNode.getUserObject() == band) {

                return bandNode;
            }
        }
        return null;
    }

    public DocumentStructureTreeNode findElementInTreeNode(DocumentStructureTreeNode parentNode, ReportElement re)
    {
        for (int k=0; k<parentNode.getChildCount(); ++k) {
            DocumentStructureTreeNode child = (DocumentStructureTreeNode)parentNode.getChildAt(k);
            if (child.getUserObject() == re) {
                return child;
            }
            if (!re.getElementGroup().equals("") || re.getParentElement() != null)
            {
                if (child.getUserObject() instanceof ElementGroup ||
                    child.getUserObject() instanceof FrameReportElement)
                {
                    DocumentStructureTreeNode newchild = findElementInTreeNode(child,re);
                    if (newchild != null) return newchild;
                }
            }
        }
        return null;
    }

    public boolean isDontHandleEvent() {
        return dontHandleEvent;
    }

    public void setDontHandleEvent(boolean dontHandleEvent) {
        this.dontHandleEvent = dontHandleEvent;
    }

    public void applyI18n(){
                // Start autogenerated code ----------------------
                jMenuItemDS_chartProperties.setText(I18n.getString("documentStructurePanel.menuItemDS_chartProperties","Chart properties"));
                jMenuItemUngroup.setText(I18n.getString("documentStructurePanel.menuItemUngroup","Ungroup"));
                // End autogenerated code ----------------------
        jMenuItemDS_cut.setText(it.businesslogic.ireport.util.I18n.getString("cut","Cut"));
        jMenuItemDS_copy.setText(it.businesslogic.ireport.util.I18n.getString("copy","Copy"));
        jMenuItemDS_paste.setText(it.businesslogic.ireport.util.I18n.getString("paste","Paste"));
        jMenuItemDS_delete.setText(it.businesslogic.ireport.util.I18n.getString("delete","Delete"));
        jMenuItemMoveUp.setText(it.businesslogic.ireport.util.I18n.getString("moveUp","Move up"));
        jMenuItemMoveDown.setText(it.businesslogic.ireport.util.I18n.getString("moveDown","Move down"));
        jMenuItemDSB_properties.setText(it.businesslogic.ireport.util.I18n.getString("bandProperties","Band properties"));
        jMenuItemDS_properties.setText(it.businesslogic.ireport.util.I18n.getString("properties","Properties"));
        jMenuItemDS_cut.setText(it.businesslogic.ireport.util.I18n.getString("cut","Cut"));
        jMenuItemDS_copy.setText(it.businesslogic.ireport.util.I18n.getString("copy","Copy"));
        jMenuItemDS_paste.setText(it.businesslogic.ireport.util.I18n.getString("paste","Paste"));
        jMenuItemDS_delete.setText(it.businesslogic.ireport.util.I18n.getString("delete","Delete"));
        jMenuItemMoveUp.setText(it.businesslogic.ireport.util.I18n.getString("moveUp","Move up"));
        jMenuItemMoveDown.setText(it.businesslogic.ireport.util.I18n.getString("moveDown","Move down"));
        jMenuItemDSB_properties.setText(it.businesslogic.ireport.util.I18n.getString("bandProperties","Band properties"));
        jMenuItemDS_properties.setText(it.businesslogic.ireport.util.I18n.getString("properties","Properties"));

        ((DefaultMutableTreeNode)this.jTreeDocument.getModel().getRoot()).setUserObject( it.businesslogic.ireport.util.I18n.getString("document","Document"));
      
    }

    public void subDatasetObjectChanged(SubDatasetObjectChangedEvent evt) {

    }

    public void setCutCopyEnabled(boolean enabled) {
        this.jMenuItemDS_cut.setEnabled(enabled);
        this.jMenuItemDS_copy.setEnabled(enabled);
        this.jMenuItemDS_delete.setEnabled(enabled);
    }

    public void setPasteEnebled(boolean enabled) {
        this.jMenuItemDS_paste.setEnabled(enabled);
    }

    public void reportBandsSelectionChanged(ReportBandsSelectionEvent evt) {
    }
    
    public void setSelectedObject( Object obj)
    {
        DefaultMutableTreeNode mtd = Misc.findNodeWithUserObject( obj, (TreeNode)this.jTreeDocument.getModel().getRoot() );
    
        if (mtd != null)
        {
            TreePath path = new TreePath( mtd.getPath() );
            jTreeDocument.setSelectionPath( path );
            jTreeDocument.scrollPathToVisible( path );
        }
    }
}
