package de.javasoft.synthetica.democenter.examples.jydocking;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;

import de.javasoft.swing.JYDockingPort;
import de.javasoft.swing.JYDockingView;
import de.javasoft.swing.jydocking.DockingManager;
import de.javasoft.swing.jydocking.IDockable;
import de.javasoft.swing.jydocking.IDockableFactory;
import de.javasoft.swing.jydocking.IDockingConstants;
import de.javasoft.swing.jydocking.IPerspectiveFactory;
import de.javasoft.swing.jydocking.IPerspectiveManager;
import de.javasoft.swing.jydocking.Perspective;
import de.javasoft.swing.jydocking.PerspectiveManager;
import de.javasoft.swing.plaf.jydocking.DefaultCloseAction;
import de.javasoft.swing.plaf.jydocking.DefaultFloatAction;
import de.javasoft.swing.plaf.jydocking.DefaultMaximizeAction;
import de.javasoft.swing.plaf.jydocking.DefaultMinimizeAction;

@SuppressWarnings("serial")
public class DynamicDockablesDemo extends JFrame
{
  private static final String PERSPECTIVE_ID = "MyPerspective-ID " + DynamicDockablesDemo.class;
  public static final String MAIN_VIEW = "main-view-ID " + DynamicDockablesDemo.class;
  public static final String EXPLORER_VIEW = "explorer-view-ID " + DynamicDockablesDemo.class;
  public static final String INFO_VIEW = "info-view-ID " + DynamicDockablesDemo.class;
  private static int counter;
  private JPanel contentPanel;

  public DynamicDockablesDemo()
  {
    add(createContentPanel());        
    installRootDockingPort();
    initializeDockingFramework(false);
        
    //clean up resources, recommended when Docking framework is used 
    //for a separate window just like the examples in the DemoCenter
    addWindowListener(new WindowAdapter()
    {
      @Override
      public void windowClosed(WindowEvent evt)
      {
        clear();
      }
    });
    
    setTitle(getClass().getSimpleName());
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    setSize(640, 480);
    setLocationRelativeTo(null);    
    setVisible(true); 
  }
    
  private JPanel createContentPanel()
  {   
    contentPanel = new JPanel(new BorderLayout(0, 0));
    contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));    
    contentPanel.add(createButtonPanel(), BorderLayout.SOUTH);
    return contentPanel;
  }
  
  private void installRootDockingPort()
  {
    contentPanel.add(new JYDockingPort(), BorderLayout.CENTER);        
  }

  private void initializeDockingFramework(boolean load)
  {
//@highlight
    DockingManager.setDockableFactory(new DockableFactory());
//@/highlight
    DockingManager.setFloatingEnabled(true);
    //DockingManager.setAutoPersist(true);

    IPerspectiveManager pm = DockingManager.getPerspectiveManager();
    pm.setFactory(new MyPerspectiveFactory());
    pm.setPersistenceKey(getClass().getSimpleName()+".xml");

    PerspectiveManager.setCurrentPerspectiveID(PERSPECTIVE_ID, true);
    //load == true means restore from disk
    pm.restorePerspectives(this, load);    
  }
  
  private JPanel createButtonPanel()
  {
    JPanel buttonPanel = new JPanel();
    buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT));

    JButton loadButton = new JButton(new AbstractAction("Load")
    {
      public void actionPerformed(ActionEvent e)
      {
        loadPerspective();
      }
    });
    buttonPanel.add(loadButton);

    JButton saveButton = new JButton(new AbstractAction("Save")
    {
      public void actionPerformed(ActionEvent e)
      {
        savePerspective();
      }
    });
    buttonPanel.add(saveButton);

    JButton resetButton = new JButton(new AbstractAction("Reset")
    {
      public void actionPerformed(ActionEvent e)
      {
        resetPerspective();
      }
    });
    buttonPanel.add(resetButton);

    JButton clearButton = new JButton(new AbstractAction("Clear")
    {
      public void actionPerformed(ActionEvent e)
      {
        clearContent();
      }
    });
    buttonPanel.add(clearButton);

    JButton addButton = new JButton(new AbstractAction("Add View")
    {
      public void actionPerformed(ActionEvent e)
      {
        addView();
      }
    });
    buttonPanel.add(addButton);

    return buttonPanel;
  }

  private void savePerspective()
  {
    IPerspectiveManager pm = DockingManager.getPerspectiveManager();
    try
    {
      pm.storePerspectives(this, pm.getPersistenceKey());
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
  }

  private void loadPerspective()
  {
    clearContent();
    installRootDockingPort();
    IPerspectiveManager pm = DockingManager.getPerspectiveManager();
    pm.restorePerspectives(this, true);
  }

  private void resetPerspective()
  {
    clearContent();
    installRootDockingPort();
    PerspectiveManager.setCurrentPerspectiveID(PERSPECTIVE_ID, true);
    PerspectiveManager.loadPerspective(PERSPECTIVE_ID, this, true);    
  }

  private void clearContent()
  {
    getContentPane().removeAll();
    clear();
    getContentPane().add(createContentPanel());
    getRootPane().revalidate();
    getRootPane().repaint();
  }
  
  private void clear()
  {
    //removes all docking components from the content panel and clears all existing dockables 
    //and perspectives - can be used when demo is executed standalone
    //DockingManager.clear();

    //when executed from within DemoCenter we have to respect dockables/perspectives of the main window
    String appId = getClass().getSimpleName();
    for (String id : DockingManager.getDockableIDs())
    { 
      if (id.contains(appId))
        DockingManager.undock(id);
    }

    IPerspectiveManager pm = DockingManager.getPerspectiveManager();
    for (Perspective p : pm.getPerspectives())
    {  
      if (p.getID().contains(appId))
        pm.removePerspective(p);
    }
    PerspectiveManager.setCurrentPerspectiveID(null, true);

    for (String id : DockingManager.getDockableIDs())
    { 
      if (id.contains(appId))
        DockingManager.unregisterDockable(id);    
    }
  }
  
  private void addView()
  {
    while(true)
    {  
      counter++;
      boolean idInUse = false;
      for (String id : DockingManager.getDockableIDs())
      {  
        if (idInUse = id.contains(new Integer(counter).toString()))
          break;
      }
      if (!idInUse)
        break;
    }; 
    IDockableFactory factory = DockingManager.getDockableFactory();
    IDockable view = factory.getDockable("New " + counter);

    IDockable mainView = DockingManager.getDockable(MAIN_VIEW);
    if (mainView != null)
      mainView.dock(view, DockingManager.getPerspectiveManager().getCurrentPerspective(), DockingManager.CENTER_REGION, 0.5f);
  }
  
  public static void main(String[] args)
  {
    EventQueue.invokeLater(new Runnable()
    {
      public void run()
      {
        try
        {
          UIManager.setLookAndFeel("de.javasoft.plaf.synthetica.SyntheticaStandardLookAndFeel");
          new DynamicDockablesDemo();
        }
        catch (Exception e)
        {
          e.printStackTrace();
        }
      }
    });
  }

  //
  //IPerspectiveFactory implementation
  //
  private static class MyPerspectiveFactory implements IPerspectiveFactory
  {
    public Perspective getPerspective(String persistentId)
    {
      if (PERSPECTIVE_ID.equals(persistentId))
        return createPerspective(PERSPECTIVE_ID);
      return null;
    }

    private Perspective createPerspective(String id)
    {      
      Perspective perspective = new Perspective(id, "MyPerspective");
      IDockableFactory factory = DockingManager.getDockableFactory();

      IDockable mainView = factory.getDockable(MAIN_VIEW);
      perspective.add(mainView);
      IDockable infoView = factory.getDockable(INFO_VIEW);
      perspective.add(infoView, mainView, IDockingConstants.SOUTH_REGION, .75f);
      IDockable explorerView = factory.getDockable(EXPLORER_VIEW);
      perspective.add(explorerView, mainView, IDockingConstants.WEST_REGION, .3f);
      return perspective;
    }
  }
  
  //
  //IDockableFactory implementation
  //
//@highlight
  private static class DockableFactory implements IDockableFactory
  {
    public IDockable getDockable(String dockableID)
    {
      //check if dockable is already created and registered
      IDockable d = DockingManager.getDockable(dockableID);
      if (d != null)
        return d;
      
      //dockableId is unknown/unregistered
      if (dockableID.equals(MAIN_VIEW))
        d = createView(MAIN_VIEW, "MainTitle", "MainTabText");
      else if (dockableID.equals(EXPLORER_VIEW))
        d = createView(EXPLORER_VIEW, "ExplorerTitle", "ExplorerTabText");
      else if (dockableID.equals(INFO_VIEW))
        d = createView(INFO_VIEW, "InfoTitle", "InfoTabText");
      else 
        d = createView(dockableID, dockableID, dockableID);
        
      return d;
    }
//@/highlight

    public JYDockingView createView(String dockableId, String title, String tabText)
    {
      //views will be automatically registered to the DockingManager on create
      JYDockingView view = new JYDockingView(dockableId, title, tabText);
      initView(view);
      return view;
    }

    private void initView(JYDockingView view)
    {
      view.addAction(new DefaultMinimizeAction(view));
      view.addAction(new DefaultMaximizeAction(view));
      view.addAction(new DefaultFloatAction(view));
      view.addAction(new DefaultCloseAction(view));
      
      view.setContentPane(createDockableContent());
    }
    
    private Container createDockableContent()
    {
      JScrollPane scroller = new JScrollPane(new JTree());
      scroller.setBorder(new EmptyBorder(0,0,0,0));
      return scroller;      
    }
  }
  
}
