/*
 * 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.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.MessageFormat;

import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;

import ilog.views.diagrammer.IlvDiagrammer;
import ilog.views.diagrammer.application.IlvDiagrammerAction;
import ilog.views.diagrammer.application.IlvDiagrammerEditBar;
import ilog.views.diagrammer.application.IlvDiagrammerMenuBar;
import ilog.views.diagrammer.application.IlvDiagrammerPaletteBar;
import ilog.views.diagrammer.application.IlvDiagrammerToolBar;
import ilog.views.diagrammer.application.IlvDiagrammerViewBar;
import ilog.views.util.IlvProductUtil;

/**
 * This example shows how to build a simple multidocument diagram editor using a
 * diagram component, {@link ilog.views.diagrammer.IlvDiagrammer}.
 * <p>
 * This example shows that the components defined in the
 * {@link ilog.views.diagrammer.application} package make it very easy to build
 * Swing applications based on a diagram component.
 * <p>
 * The example is a simplified version of the predefined application
 * {@link ilog.views.diagrammer.application.IlvDiagrammerApplication}. You can
 * use this code as a basis to create your own customized application.
 */
public class DiagramEditor extends JFrame {
  // The desktop pane that contains the diagram components.
  private JDesktopPane desktopPane;
  // The style sheet to use.
  private URL styleSheet;

  // The default palette.
  private final static String PALETTE = "file:data/palette.xml";
  // The default style sheet.
  private final static String STYLE_SHEET = "file:data/basic.css";
  // The title for new frames.
  private static final String UNNAMED_FORMAT = "unnamed ({0})";
  // The index used to differentiate new frames.
  private int unnamedCount = 1;

  /**
   * The main method of the application.
   */
  public static void main(String[] args) {
    // This sample uses JViews Diagrammer features. When deploying an
    // application that includes this code, you need to be in possession
    // of a Perforce JViews Diagrammer Deployment license.
    IlvProductUtil.DeploymentLicenseRequired(IlvProductUtil.JViews_Diagrammer_Deployment);

    // Create an instance of the editor, and show it.
    //
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      Override
      public void run() {
        new DiagramEditor().setVisible(true);
      }
    });
  }

  /**
   * Creates a new editor.
   */
  public DiagramEditor() {
    // Set up the frame.
    //
    super("Diagram Editor");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLocation(100, 100);
    setSize(600, 400);

    // Create the palette URL.
    //
    URL paletteURL = null;
    try {
      paletteURL = new URL(PALETTE);
    } catch (MalformedURLException e) {
      e.printStackTrace();
    }

    // Create the style sheet URL.
    //
    try {
      styleSheet = new URL(STYLE_SHEET);
    } catch (MalformedURLException e) {
      e.printStackTrace();
    }

    // Create and add the desktop pane.
    //
    desktopPane = new JDesktopPane();

    getContentPane().setLayout(new BorderLayout());
    getContentPane().add(desktopPane, BorderLayout.CENTER);

    // Create a panel at the north of the frame, It will contain the edit
    // toolbar
    // and the palette toolbar.
    //
    JPanel northPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
    getContentPane().add(northPanel, BorderLayout.NORTH);

    // Create the Edit toolbar.
    //
    IlvDiagrammerToolBar editToolBar = new IlvDiagrammerEditBar();

    // By default, the "New" action just clears the current diagram component.
    // Here, to create a new internal frame instead, the method overrides
    // the implementation of the _new action by adding a listener to it.
    //
    IlvDiagrammerAction._new.setHandler(new IlvDiagrammerAction.Handler() {
      Override
      public void perform(IlvDiagrammerAction action, IlvDiagrammer diagrammer, ActionEvent event) throws Exception {
        DiagramEditor.this.newDiagram();
      }
    });
    northPanel.add(editToolBar);

    // Create the palette toolbar and put it next to the edit toolbar.
    //
    try {
      IlvDiagrammerToolBar paletteBar = new IlvDiagrammerPaletteBar(paletteURL, styleSheet, JToolBar.HORIZONTAL);
      northPanel.add(paletteBar);
    } catch (Exception e) {
      e.printStackTrace();
    }

    // Create a View toolbar (to control zooming, panning, and so on), and
    // add it vertically on the left of the frame.
    //
    JToolBar controlToolBar = new IlvDiagrammerViewBar(JToolBar.VERTICAL);
    getContentPane().add(controlToolBar, BorderLayout.WEST);

    // Create a standard Diagrammer menu bar.
    //
    JMenuBar menuBar = new IlvDiagrammerMenuBar();
    setJMenuBar(menuBar);

    // Once ready, create the initial frame.
    //
    SwingUtilities.invokeLater(new Runnable() {
      Override
      public void run() {
        newDiagram();
      }
    });
  }

  /**
   * Creates a new internal frame with a new diagram component in it.
   */
  public IlvDiagrammer newDiagram() {
    // Create and set up the new diagram component.
    //
    final IlvDiagrammer diagrammer = new IlvDiagrammer();
    diagrammer.setScrollable(true);
    diagrammer.setSelectMode(true);
    diagrammer.setEditingAllowed(true);

    // Set the style sheet.
    //
    try {
      diagrammer.setStyleSheet(styleSheet);
    } catch (Exception e) {
      e.printStackTrace();
    }

    // Compute the title of the new frame ("unnamed (x)").
    //
    String title = MessageFormat.format(UNNAMED_FORMAT, new Object[] { Integer.valueOf(unnamedCount++) });

    // Create the new internal frame, and add the diagram component to it.
    //
    final JInternalFrame frame = new JInternalFrame(title, true, true, true, true);
    frame.getContentPane().add(diagrammer);
    frame.setSize(400, 300);

    // Watch changes to the diagram data file (through a PropertyChangeListener)
    // to update the frame title when necessary.
    //
    diagrammer.addPropertyChangeListener(new PropertyChangeListener() {
      Override
      public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("dataFile")) {
          frame.setTitle(((URL) evt.getNewValue()).getPath());
        }
      }
    });

    // Add and show the new frame.
    //
    // Wait until the desktop pane is showing before we show the new frame,
    // this is to avoid a bug in JDK 1.3.1.
    if (desktopPane.isShowing()) {
      desktopPane.add(frame);
      frame.setVisible(true);
    } else {
      desktopPane.addHierarchyListener(new HierarchyListener() {
        Override
        public void hierarchyChanged(HierarchyEvent e) {
          if (desktopPane.isShowing()) {
            desktopPane.add(frame);
            frame.setVisible(true);
            desktopPane.removeHierarchyListener(this);
          }
        }
      });
    }

    // All done!
    //
    return diagrammer;
  }
}