/*
 * DockingContainer.java
 *
 * Created on January 25, 2006, 5:22 PM
 */

package it.businesslogic.ireport.gui.docking;

import java.awt.Component;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetContext;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.util.Vector;

/**
 *
 * @author  gtoffoli
 */
public class DockingContainer extends javax.swing.JPanel {
    
    public static final int INSERT_MODE_SHAREDPOSTION = 0;
    public static final int INSERT_MODE_NEWPOSITION = 1;
    
    private int oldWidth = 0;
    private boolean compressed = false;
    
    private Vector panelViews = new Vector();
    private Vector tabPanes = new Vector();
    private int positions = 0;
    
    private DropTarget dropTarget;
    private DropTargetListener dtListener;
  
    /** Creates new form DockingContainer */
    public DockingContainer() {
        initComponents();
        
        this.dtListener = new DTListener();
        // component, ops, listener, accepting
        this.dropTarget = new DropTarget(this, 
            DnDConstants.ACTION_MOVE,
            this.dtListener,
        true);
    }
    
    /**
     * Add a component under the other
     *
     */
    public void addPanel(String name, Component component)
    {
        insertPanel(positions, name, component);
        
    }
    
    public void insertPanel(int position, String name, Component component, int insertMode)
    {
        if (component == null) return;
        if (name == null) name = "Panel";
        
        //System.out.println("Added panel " + name + " at position " + position);        
        if (position >= positions)
        {
            position = positions;
            positions++;
        }
        else if (insertMode == INSERT_MODE_NEWPOSITION)
        {
            for (int i=0; i<getPanelViews().size(); ++i)
            {
                PanelView pv = (PanelView)getPanelViews().elementAt(i);

                if (pv.getPosition() >= position)
                {
                    pv.setPosition( pv.getPosition()+1 );
                }
            }
            positions++;
        }
        
        panelViews.add( new PanelView(name, component, position) );
        recreateAll();
        
    }
    /**
     * Add a component at position
     *
     */
    public void insertPanel(int position, String name, Component component)
    {
        insertPanel(position, name, component, INSERT_MODE_NEWPOSITION);
    }
    
    /**
     * Add a component at position
     *
     */
    public void removePanel(Component component)
    {
        
        int position = -1;
        for (int i=0; i<getPanelViews().size(); ++i)
        {
            PanelView pv = (PanelView)getPanelViews().elementAt(i);
            
            if (pv.getComponent() == component)
            {
                position = pv.getPosition();
                //System.out.println("removing panel " + pv.getName() + " at position " + pv.getPosition());
                getPanelViews().remove(pv);
                break;
            }
        }
        
        
        
        // If "position" is not used, normalize all...
        if (position >= 0)
        {
            boolean found = false;
            for (int i=0; i<getPanelViews().size(); ++i)
            {
                PanelView pv = (PanelView)getPanelViews().elementAt(i);
            
                if (pv.getPosition() == position)
                {
                    found = true;
                    break;
                }
            }
            
            if (!found)
            {
                for (int i=0; i<getPanelViews().size(); ++i)
                {
                    PanelView pv = (PanelView)getPanelViews().elementAt(i);

                    if (pv.getPosition() > position)
                    {
                        pv.setPosition( pv.getPosition()-1);
                    }
                }
                positions--;
            }
            recreateAll();
        }
    }
    
    /**
     * Use this panelView to describe the panel to move. Only component and name are used
     * to move the component in the newPosition
     * panelView.component is removed then inserted again in newPosition with label panelView.name
     */
    public void moveComponent(PanelView panelView, int newPosition)
    {
        moveComponent(panelView, newPosition, INSERT_MODE_NEWPOSITION);
    }
    
    /**
     * Use this panelView to describe the panel to move. Only component and name are used
     * to move the component in the newPosition
     * panelView.component is removed then inserted again in newPosition with label panelView.name
     */
    public void moveComponent(PanelView panelView, int newPosition, int mode)
    {
        removePanel(panelView.getComponent());
        insertPanel(newPosition,panelView.getName(), panelView.getComponent(), mode);
    }
    
    /**
     * Use this panelView to describe the panel to move. Only component and name are used
     * to move the component in the newPosition
     * panelView.component is removed then inserted again in newPosition with label panelView.name
     */
    public void mergePosition(int newPosition)
    {
        if (newPosition >= positions) return;
        if ( newPosition == 0 && positions>1) newPosition=1;
        for (int i=0; i<getPanelViews().size(); ++i)
        {
            PanelView pv = (PanelView)getPanelViews().elementAt(i);

            if (pv.getPosition() >= newPosition)
            {
                pv.setPosition( pv.getPosition()-1);
            }
            
            System.out.println( pv.getName() + "-> " + pv.getPosition());
        }
        
        
        
        positions--;
        recreateAll();
    }
    
    
    
    public void recreateAll()
    {
        this.removeAll();
        
        if (positions > 0)
        {
            if (compressed)
            {
                compressed = false;
                this.setSize(getOldWidth(), 1);
            }
            
            
            tabPanes.removeAllElements();
            Vector tabbedPanes = new Vector();
            if (positions == 0) return;
        
            add( addComponents(0),java.awt.BorderLayout.CENTER);
            this.updateUI();
        }
        else
        {
            compressed = true;
            setOldWidth( getSize().width);
            this.setSize(0, 1);
        }
    }
    
    public void setSelectedComponent(Component component)
    {
        for (int i=0; i<tabPanes.size(); ++i)
        {
            JDraggableTabbedPane tab = (JDraggableTabbedPane)tabPanes.get(i);
            try {
               tab.setSelectedComponent( component );
               break;
            } catch (Exception ex) {}
        }
    }
    
    public Component addComponents(int pos)
    {
        
        JDraggableTabbedPane jTabbedPane = new JDraggableTabbedPane();
        jTabbedPane.setPosition(pos);
        jTabbedPane.setFont(new java.awt.Font("Tahoma", 0, 11));
        jTabbedPane.setDockingContainer(this);
        tabPanes.add(jTabbedPane);
                
        for (int i=0; i<getPanelViews().size(); ++i)
        {
            PanelView pv = (PanelView)getPanelViews().elementAt(i);
            
            if (pv.getPosition() == pos)
            {
                jTabbedPane.addTab(pv.getName(), pv.getComponent());
            }
            
            //System.out.println("Adding " + pv.getName() + " on position " + pos + "/" + positions);
        }
        
        if (pos < positions-1)
        {
            javax.swing.JSplitPane jSplitPane = new javax.swing.JSplitPane();
            jSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
            
            jSplitPane.setResizeWeight( 1.0/(positions-pos));
            jSplitPane.setLeftComponent(jTabbedPane);
            jSplitPane.setRightComponent(  addComponents(pos+1) );
            jSplitPane.setDividerSize(5);
            return jSplitPane;
        }
        else
        {
            return jTabbedPane;
        }
    }
    
    
    public Vector getPanelViews() {
        return panelViews;
    }

    public void setPanelViews(Vector panelViews) {
        this.panelViews = panelViews;
    }

    public int getOldWidth() {
        return oldWidth;
    }

    public void setOldWidth(int oldWidth) {
        this.oldWidth = oldWidth;
    }

    public boolean isCompressed() {
        return compressed;
    }

    public void setCompressed(boolean compressed) {
        this.compressed = compressed;
    }
    
    /** 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() {

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

    }// </editor-fold>//GEN-END:initComponents
    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables
      /**
   * DTListener
   * a listener that tracks the state of the operation
   * @see java.awt.dnd.DropTargetListener
   * @see java.awt.dnd.DropTarget
   */
  class DTListener implements DropTargetListener {


    /**
     * start "drag under" feedback on component
     * invoke acceptDrag or rejectDrag based on isDragOk
     */
    public void dragEnter(DropTargetDragEvent e) {
      e.acceptDrag(e.getDropAction());        
    }

    /**
     * continue "drag under" feedback on component
     * invoke acceptDrag or rejectDrag based on isDragOk
     */
    public void dragOver(DropTargetDragEvent e) {
      e.acceptDrag(e.getDropAction());    
    }
    
    public void dropActionChanged(DropTargetDragEvent e) {
    }
    
    public void dragExit(DropTargetEvent e) {
    }

    /**
     * perform action from getSourceActions on
     * the transferrable
     * invoke acceptDrop or rejectDrop
     * invoke dropComplete
     * if its a local (same JVM) transfer, use StringTransferable.localStringFlavor
     * find a match for the flavor
     * check the operation
     * get the transferable according to the chosen flavor
     * do the transfer
     */
    public void drop(DropTargetDropEvent dtde) {
        try {
           
            DropTargetContext context = dtde.getDropTargetContext();

            Transferable tr = dtde.getTransferable();

            DataFlavor[] df = tr.getTransferDataFlavors();

            if (df[0].getHumanPresentableName().equals("it.businesslogic.ireport.gui.docking.PanelView"))
            {
                java.awt.datatransfer.DataFlavor myFlavor = new java.awt.datatransfer.DataFlavor(it.businesslogic.ireport.gui.docking.PanelView.class, it.businesslogic.ireport.gui.docking.PanelView.class.getName());
                it.businesslogic.ireport.gui.docking.PanelView panelView = (it.businesslogic.ireport.gui.docking.PanelView)tr.getTransferData( myFlavor );
                
                
                if (panelView.getDockingContainer() != DockingContainer.this)
                {
                    panelView.getDockingContainer().removePanel(panelView.getComponent());
                    DockingContainer.this.insertPanel(0, panelView.getName(), panelView.getComponent());
                }
            }
           
            context.dropComplete(true);
        } catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }

  }
}
