/*
 * Licensed Materials - Property of Rogue Wave Software, Inc. 
 * © Copyright Rogue Wave Software, Inc. 2014, 2015 
 * © 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 ilog.views.IlvRect;
import ilog.views.diagrammer.IlvDiagrammer;
import ilog.views.diagrammer.application.IlvDiagrammerAction;
import ilog.views.diagrammer.application.IlvDiagrammerApplication;
import ilog.views.diagrammer.application.IlvDiagrammerPaletteBar;
import ilog.views.util.IlvProductUtil;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.beans.PropertyVetoException;
import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;
import java.util.StringTokenizer;

/**
 * This example shows how to build a business process modeler
 * based on a diagram component, {@link ilog.views.diagrammer.IlvDiagrammer}.
 * <p>
 * The example is based on the predefined class
 * {@link ilog.views.diagrammer.application.IlvDiagrammerApplication}
 * supplied with Rogue Wave JViews Diagrammer.
 * <p>
 * You can also look at the "Diagram Editor" example, which shows how to
 * build your own customized application using the components of
 * the {@link ilog.views.diagrammer.application} package
 * (toolbars, menus, and so on).
 */
public class ProcessModeler extends IlvDiagrammerApplication
{
  // The resource bundle used to get localized messages for
  // this class.
  //
  private ResourceBundle bundle;
  
  private URL[] styleSheets;
  private JComboBox combo;
  private JTextField descriptionField;
 
  /**
   * Creates a new process modeler.
   */ 
  public ProcessModeler()
  {
    super();

    // This sample uses JViews Diagrammer features. When deploying an
    // application that includes this code, you need to be in possession
    // of a Rogue Wave JViews Diagrammer Deployment license.
    IlvProductUtil.DeploymentLicenseRequired(
        IlvProductUtil.JViews_Diagrammer_Deployment);

    // Load the property file.
    //
    bundle = ResourceBundle.getBundle("modeler");
    
    // Set default arguments.
    //
    setDefaultArgs(new String[]{
      "-title", bundle.getString("ProcessModeler.FrameTitle"),
      "-mdi",
      "-tree",
      "-psheet",
      "-edit",
      "-style", "data/default.css",
      "-palette", "data/bpm-palette.xml",
      "-data", "data/hotline.idpr"
    });
  }

  /**
   * Maximizes the initial frame.
   */ 
  protected void ready()
  {
    super.ready();
    
    JInternalFrame[] frames = getDesktopPane().getAllFrames();
    if(frames != null && frames.length > 0){
      try {
        frames[0].setMaximum(true);
      } catch (PropertyVetoException e) {
      }
    }
    if(getCurrentDiagrammer() != null){
      adjustView(getCurrentDiagrammer());
    }
  }

  /**
   * Initializes the GUI.
   * @param contentPane The container of the application or applet.
   */ 
  public void init(Container contentPane)
  {
    super.init(contentPane);
    
    // Create the combo box that lets the user choose a diagram.
    //
    JPanel styleSheetPanel = new JPanel(new GridBagLayout());
    JToolBar[] palettes = getPaletteToolBars();
    Container toolbarPanel = palettes[0].getParent();
    JPanel newPanel = new JPanel(new BorderLayout());
    newPanel.add(toolbarPanel, BorderLayout.CENTER);
    newPanel.add(styleSheetPanel, BorderLayout.SOUTH);
    contentPane.remove(toolbarPanel);
    contentPane.add(newPanel, BorderLayout.NORTH);
    
    GridBagConstraints c = new GridBagConstraints();
    c.gridy = 0;
    c.insets = new Insets(5, 5, 5, 5);
    c.weightx = 0;
    c.fill = GridBagConstraints.NONE;
    
    JLabel label = new JLabel(bundle.getString("ProcessModeler.ChooseStyleSheet"));
    c.gridx = 0;
    styleSheetPanel.add(label, c);
    
    styleSheets = readStyleSheets();
    
    combo = new JComboBox(styleSheets);
    combo.setRenderer(new DefaultListCellRenderer(){
      public Component getListCellRendererComponent(
              JList list,
              Object value,
              int index,
              boolean isSelected,
              boolean cellHasFocus)
      {
        JLabel label =
                (JLabel) super.getListCellRendererComponent(list,
                                                            value,
                                                            index,
                                                            isSelected,
                                                            cellHasFocus);
        label.setText(getProperty((URL)value,
                                  "ShortDescription"));
        return label;
      }
    });
    combo.addItemListener(new ItemListener(){
      public void itemStateChanged(ItemEvent e)
      {
        if(e.getStateChange() == ItemEvent.SELECTED){
          loadStyleSheet((URL)combo.getSelectedItem());
        }
      }
    });
    c.gridx = 1;
    styleSheetPanel.add(combo, c);
    
    descriptionField = new JTextField();
    descriptionField.setEditable(false);
    String initialDescr = getProperty(styleSheets[0], "LongDescription");
    descriptionField.setText(initialDescr);
    c.weightx = 1;
    c.gridx = 2;
    c.fill = GridBagConstraints.HORIZONTAL;
    styleSheetPanel.add(descriptionField, c);
  }
  
  /**
   * Reads the list of style sheets from the property file.
   */ 
  private URL[] readStyleSheets()
  {
    ArrayList l = new ArrayList();
    try {
      URL documentBase;
      
      if(isApplet()){
        documentBase = getDocumentBase();
      } else {
        documentBase = new URL("file:./");
      }
      
      String list = bundle.getString("ProcessModeler.StyleSheetList");
      StringTokenizer tok = new StringTokenizer(list, " ,");
      while(tok.hasMoreTokens()){
        String name = tok.nextToken();
        URL styleSheet = new URL(documentBase, "data/"+name+".css");
        l.add(styleSheet);
      }
    } catch(Exception ex){
      IlvDiagrammerAction.error(
              getApplicationContentPane(),
              bundle,
              "ProcessModeler.ErrorWhileListingStyleSheets",
              null,
              ex);
    }
    return (URL[]) l.toArray(new URL[0]);
  }
  
  private String getProperty(URL url, String property)
  {
    String key = url.toExternalForm();
    key = key.substring(key.lastIndexOf('/')+1);
    key = key.substring(0, key.lastIndexOf('.'));
    return bundle.getString("ProcessModeler."+key+"."+property);
  }
  
  /**
   * Loads a new style sheet.
   */ 
  private void loadStyleSheet(URL newStyleSheet)
  {
    descriptionField.setText(getProperty(newStyleSheet, "LongDescription"));
    
    // Change the style sheet for the other open diagrams.
    //
    IlvDiagrammer[] diagrammers = getDiagrammers();
    for (int i = 0; i < diagrammers.length; i++) {
      IlvDiagrammer d = diagrammers[i];
      try {
        d.setStyleSheet(newStyleSheet);
      } catch (Exception e) {
        IlvDiagrammerAction.error(
                getApplicationContentPane(),
                bundle,
                "ProcessModeler.ErrorWhileLoadingStyleSheet",
                new Object[] {
                  newStyleSheet
                },
                e);
      }
      
      // Relayout the diagram, because the new style may cause
      // nodes to overlap.
      //
      d.layoutAllNodes();
      d.layoutLinks();
      
      // Center the diagram nicely.
      //
      adjustView(d);

      // Update the icons in the tree.
      //
      if(getTree() != null)
        getTree().updateIcons();
    }
    
    // Update the palette toolbars.
    //
    JToolBar[] palettes = getPaletteToolBars();
    for (int i = 0; i < palettes.length; i++) {
      JToolBar palette = palettes[i];
      if(palette instanceof IlvDiagrammerPaletteBar){
        try {
          ((IlvDiagrammerPaletteBar)palette).setStyleSheet(
                  newStyleSheet);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
                
    // Make sure new buffers use the new style sheet.
    //
    setStyleSheetURL(newStyleSheet);
  }

  /**
   * Changes the zoom factor.
   */ 
  protected IlvDiagrammer createDiagrammer()
  {
    IlvDiagrammer diagrammer = super.createDiagrammer();
    diagrammer.setZoomFactor(1.5);
    return diagrammer;
  }

  /**
   * Changes zooms and translates the view so that the diagram is best
   * visible.
   * @param d The diagram component.
   */ 
  private void adjustView(IlvDiagrammer d)
  {
    d.resetZoom();
    d.zoomOut();
      
    IlvRect bbox =
            d.getEngine().getGrapher().computeBBox(d.getView().getTransformer());
    Dimension size = d.getView().getSize();
      
    float x, y;
    float margin = 10;
    if(bbox.width > size.width){
      x = margin;
    } else {
      x = (size.width - bbox.width)/2;
    }
    if(bbox.height > size.height){
      y = margin;
    } else {
      y = (size.height - bbox.height)/2;
    }
    d.getView().translate(x - bbox.x, y - bbox.y, true);
  }

  /**
   * The main method of the application. You must always supply your
   * own main when subclassing
   * {@link ilog.views.diagrammer.application.IlvDiagrammerApplication}.
   * @param args The command-line arguments.
   */ 
  public static void main(final String[] args)
  {
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        // Create the new modeler application and show it.
        //
        new ProcessModeler().init(args);
      }
    });
  }
}