/*
 * Licensed Materials - Property of Perforce Software, Inc. 
 * © Copyright Perforce Software, Inc. 2014, 2021 
 * © Copyright IBM Corp. 2009, 2014
 * © Copyright ILOG 1996, 2009
 * All Rights Reserved.
 *
 * Note to U.S. Government Users Restricted Rights:
 * The Software and Documentation were developed at private expense and
 * are "Commercial Items" as that term is defined at 48 CFR 2.101,
 * consisting of "Commercial Computer Software" and
 * "Commercial Computer Software Documentation", as such terms are
 * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4,
 * as applicable.
 */

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.net.URL;

import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;

import ilog.views.IlvApplyObject;
import ilog.views.IlvDefaultManagerFrame;
import ilog.views.IlvGrapher;
import ilog.views.IlvGraphic;
import ilog.views.IlvGraphicBag;
import ilog.views.IlvGraphicEnumeration;
import ilog.views.IlvHandlesSelection;
import ilog.views.IlvManager;
import ilog.views.IlvManagerFrame;
import ilog.views.IlvManagerView;
import ilog.views.IlvObjectWithSelection;
import ilog.views.IlvTransformer;
import ilog.views.accelerator.IlvExpandSelectionAccelerator;
import ilog.views.accelerator.IlvIdentityAccelerator;
import ilog.views.accelerator.IlvPopupMenuAccelerator;
import ilog.views.accelerator.IlvZoomInAccelerator;
import ilog.views.accelerator.IlvZoomOutAccelerator;
import ilog.views.graphic.linkbundle.IlvDefaultLinkBundleFrame;
import ilog.views.graphic.linkbundle.IlvLinkBundle;
import ilog.views.graphic.linkbundle.IlvLinkBundleFrame;
import ilog.views.interactor.IlvExpandCollapseInteractor;
import ilog.views.interactor.IlvSelectInteractor;
import ilog.views.interactor.IlvZoomViewInteractor;
import ilog.views.swing.IlvJManagerViewControlBar;
import ilog.views.swing.IlvJScrollManagerView;
import ilog.views.swing.IlvPopupMenuContext;
import ilog.views.swing.IlvPopupMenuManager;
import ilog.views.swing.IlvSimplePopupMenu;
//import ilog.views.util.IlvProductUtil;
import ilog.views.util.IlvResourceUtil;
import ilog.views.util.swing.IlvSwingUtil;

/**
 * This sample shows how to expand and collapse sub managers
 * and link bundles.
 */
SuppressWarnings("serial")
public class ExpandCollapseInteractions extends JRootPane
{

  {
    // This sample uses JViews Diagrammer features. When deploying an
    // application that includes this code, you need 
    // a Perforce JViews Diagrammer Deployment license.
//    IlvProductUtil.DeploymentLicenseRequired(
//        IlvProductUtil.JViews_Diagrammer_Deployment);
  }

  // the grapher
  IlvGrapher grapher;

  // the view
  IlvManagerView mgrview;


  /**
   * Initializes the sample.
   */
  public void init()
  {
    // Creates the top grapher:
    grapher = new IlvGrapher();

    // Creates a view associated to the grapher
    mgrview = new IlvManagerView(grapher);

    // Clicking on the expand-collapse icon should expand and collapse
    mgrview.setCollapseExpandIconsEnabled(true);

    // for the pop-up menu
    // register view mgrview to the pop-up manager
    IlvPopupMenuManager.registerView(mgrview);

    // register the menus under different names
    IlvPopupMenuManager.registerMenu("COLLAPSE", createMenu(true));
    IlvPopupMenuManager.registerMenu("EXPAND", createMenu(false));

    // create the scroll manager view 
    IlvJScrollManagerView scrollManView = new IlvJScrollManagerView(mgrview);

    // Some settings on the manager view and on the scroll manager view
    mgrview.setAntialiasing(true);
    mgrview.setKeepingAspectRatio(true);
    mgrview.setBackground(Color.white);
    mgrview.setForeground(SystemColor.windowText);
    Color xc = SystemColor.windowText;
    xc = new Color(255-xc.getRed(), 255-xc.getGreen(), 255-xc.getBlue());
    mgrview.setDefaultXORColor(xc);
    mgrview.setDefaultGhostColor(SystemColor.windowText);
    mgrview.setZoomFactorRange(0.02, 10.0);
    mgrview.setWheelZoomingEnabled(true);
    scrollManView.setWheelScrollingEnabled(true);

    // Settings parameters for selection handles
    IlvHandlesSelection.defaultHandleColor = Color.red;
    IlvHandlesSelection.defaultHandleBackgroundColor = Color.white;
    IlvHandlesSelection.defaultHandleShape = IlvHandlesSelection.SQUARE_SHAPE;

    // create the standard control bar
    IlvJManagerViewControlBar controlBar = new IlvJManagerViewControlBar();
    URL expandIconURL = getClass().getResource("expandButton.gif");
    controlBar.addInteractorButton(null, 
                                   expandIconURL,
                                   new ExpandCollapseInteractor(),
                                   "Expand or Collapse");
    controlBar.setView(mgrview);

    // modify the interactors so that the demo looks better
    ((IlvSelectInteractor)controlBar.getSelectInteractor()).setOpaqueMove(true);
    ((IlvSelectInteractor)controlBar.getSelectInteractor()).setOpaqueResize(true);
    ((IlvZoomViewInteractor)controlBar.getZoomViewInteractor()).setPermanent(true);

    // set the initial interactor
    mgrview.setInteractor(controlBar.getSelectInteractor());

    // Install Zoom Accelerators
    // Control-I = identity
    // Control-Z = zoom in
    // Control-U = zoom out
    // Control-E = expand/collapse selected 
    // F1        = pop-ups
    grapher.addAccelerator(new IlvIdentityAccelerator(KeyEvent.KEY_PRESSED, KeyEvent.VK_I, KeyEvent.CTRL_MASK));
    grapher.addAccelerator(new IlvZoomOutAccelerator(KeyEvent.KEY_PRESSED, KeyEvent.VK_U, KeyEvent.CTRL_MASK));
    grapher.addAccelerator(new IlvZoomInAccelerator(KeyEvent.KEY_PRESSED, KeyEvent.VK_Z, KeyEvent.CTRL_MASK));
    grapher.addAccelerator(new IlvExpandSelectionAccelerator(KeyEvent.KEY_PRESSED, KeyEvent.VK_E, InputEvent.CTRL_MASK));
    grapher.addAccelerator(new IlvPopupMenuAccelerator(KeyEvent.KEY_PRESSED, KeyEvent.VK_F1, 0));


    // put manager view and top panel together
    getContentPane().setLayout(new BorderLayout(0, 0));
    getContentPane().add(scrollManView, BorderLayout.CENTER);
    getContentPane().add(controlBar, BorderLayout.NORTH);

    // load a sample grapher
    try {
      grapher.read(
        IlvSwingUtil.getRelativeURL(this, "data/graph.ivl"));
      installPopupMenus(grapher);
      mgrview.setTransformer(new IlvTransformer());
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * Install the pop-up menus in all link bundles and managers.
   */
  private void installPopupMenus(IlvGraphicBag bag)
  {
    IlvGraphicEnumeration e = bag.getObjects();
    while (e.hasMoreElements()) {
      IlvGraphic g = e.nextElement();
      if (g instanceof IlvManager) {
        IlvManager manager = (IlvManager)g;
        manager.setPopupMenuName("COLLAPSE");
        installPopupMenus(manager);
      } else if (g instanceof IlvLinkBundle) {
        IlvLinkBundle bundle = (IlvLinkBundle)g;
        bundle.setPopupMenuName("COLLAPSE");
        installPopupMenus(bundle);
      }
    }
  }

  /**
   * Creates a pop-up menu to expand or collapse.
   */
  private JPopupMenu createMenu(boolean collapse)
  {
    // create the action listener for the pop-up menu
    ActionListener actionListener = new ActionListener() {
      Override
      public void actionPerformed(ActionEvent e) {

        // retrieve the selected menu item
        JMenuItem m = (JMenuItem)e.getSource();

        // retrieve the graphic that has this pop-up menu
        IlvPopupMenuContext context = IlvPopupMenuManager.getPopupMenuContext(m);
        IlvGraphic graphic = context.getGraphic();

        // do the action
        if (IlvSimplePopupMenu.getMenuItemText(m).equals("Collapse")) {
          if (graphic instanceof IlvObjectWithSelection) {
            IlvObjectWithSelection obj = (IlvObjectWithSelection)graphic;
            if (graphic.getGraphicBag() != null) {
              graphic.getGraphicBag().applyToObject(graphic, new IlvApplyObject() {
                  Override
                  public void apply(IlvGraphic g, Object arg) {
                    ((IlvObjectWithSelection)g).setCollapsed(true);
                  }
              }, null, true);
            } else {
              obj.setCollapsed(true);
            }
            graphic.setPopupMenuName("EXPAND");
          }
        }
        if (IlvSimplePopupMenu.getMenuItemText(m).equals("Expand")) {
          if (graphic instanceof IlvObjectWithSelection) {
            IlvObjectWithSelection obj = (IlvObjectWithSelection)graphic;
            if (graphic.getGraphicBag() != null) {
              graphic.getGraphicBag().applyToObject(graphic, new IlvApplyObject() {
                  Override
                  public void apply(IlvGraphic g, Object arg) {
                    ((IlvObjectWithSelection)g).setCollapsed(false);
                  }
              }, null, true);
            } else {
              obj.setCollapsed(false);
            }
            graphic.setPopupMenuName("COLLAPSE");
          }
        }
      }
    };


    IlvSimplePopupMenu menu =
      new IlvSimplePopupMenu(
              "Menu1",
              collapse ? "Collapse" : "Expand",
              null,
              actionListener) {

        // configure check box of the pop-up before it gets displayed
        Override
        protected void beforeDisplay(IlvPopupMenuContext context) {
          // always call super.beforeDisplay first
          super.beforeDisplay(context);
          // retrieve the graphic
          IlvGraphic graphic = context.getGraphic();
          // deselect all objects in the manager
          IlvGraphicBag bag = graphic.getGraphicBag();
          while (bag != null && !(bag instanceof IlvManager)) {
            bag = ((IlvGraphic)bag).getGraphicBag();
          }
          if (bag instanceof IlvManager)
            ((IlvManager)bag).deSelectAll(true, true);
          // select this graphic;
          bag = graphic.getGraphicBag();
          // from overview link
          if (bag instanceof IlvLinkBundle) {
            IlvLinkBundle ownerBundle = (IlvLinkBundle)graphic.getGraphicBag();
            if (ownerBundle.getOverviewLink() == graphic) {
              graphic = ownerBundle;
              bag = graphic.getGraphicBag();
            }
          }
          if (bag instanceof IlvObjectWithSelection) {
            ((IlvObjectWithSelection)bag).setSelected(graphic, true, true);
          }
        }
    };

    return menu;

  }

  public static void main(String[] args) 
  {
    // Sun recommends putting the entire GUI initialization into the
    // AWT thread
    SwingUtilities.invokeLater(
      new Runnable() {
        Override
        public void run() {
          ExpandCollapseInteractions app = new ExpandCollapseInteractions();
          app.init();

          JFrame frame = new JFrame("Expand Manager and Link Bundle Sample");
          frame.setSize(520, 370);
          frame.getContentPane().add(app);
          frame.addWindowListener(new ExitOnWindowClosing());
          frame.setVisible(true);
        }
      });
  }

  /**
   * Exit on windows closing.
   */
  static class ExitOnWindowClosing extends WindowAdapter
  {
    public ExitOnWindowClosing()
    {}

    Override
    public void windowClosing(WindowEvent e) {
      System.exit(0);
    }
  }

  /**
   * An interactor to expand or collapse.
   * When this interactor is active, the expand/collapse icons are made
   * invisible.
   */
  static class ExpandCollapseInteractor extends IlvExpandCollapseInteractor
  {
    public ExpandCollapseInteractor()
    {
      super();
    }

    /**
     * Attach the interactor.
     */
    Override
    protected void attach(IlvManagerView view)
    {
      super.attach(view);
      setCollapseExpandIconsEnabled(getManager(), false);
    }

    /**
     * Detach the interactor.
     */
    Override
    protected void detach()
    {
      setCollapseExpandIconsEnabled(getManager(), true);
      super.detach();
    }

    /**
     * Enable or disable the expand icons.
     */
    private void setCollapseExpandIconsEnabled(IlvGraphicBag bag, boolean on)
    {
      final boolean fon = on;
      IlvGraphicEnumeration e = bag.getObjects();
      while (e.hasMoreElements()) {
        IlvGraphic g = e.nextElement();
        if (g instanceof IlvManager) {
          IlvManagerFrame frame = ((IlvManager)g).getFrame();
          if (frame instanceof IlvDefaultManagerFrame) {
            final IlvDefaultManagerFrame dframe = (IlvDefaultManagerFrame)frame;
            g.getGraphicBag().applyToObject(g, new IlvApplyObject() {
                 Override
                public void apply(IlvGraphic g, Object arg) {
                   dframe.setShowingExpandCollapseIcon(fon);
                 }
              }, null, true);
          }
          setCollapseExpandIconsEnabled((IlvGraphicBag)g, on); 
        }
        if (g instanceof IlvLinkBundle) {
          final IlvLinkBundleFrame frame = ((IlvLinkBundle)g).getFrame();
          if (frame instanceof IlvDefaultLinkBundleFrame) {
            final IlvDefaultLinkBundleFrame dframe = (IlvDefaultLinkBundleFrame)frame;
            g.getGraphicBag().applyToObject(g, new IlvApplyObject() {
                 Override
                public void apply(IlvGraphic g, Object arg) {
                   dframe.setShowingExpandCollapseIcon(fon);
                 }
              }, null, true);
          }
          setCollapseExpandIconsEnabled((IlvGraphicBag)g, on); 
        }
      }
    }
  }
}