/*
 * 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.
 */

package newgraphics;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.Rectangle2D;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JRootPane;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;

import ilog.views.IlvDirection;
import ilog.views.IlvGraphic;
import ilog.views.IlvGraphicEnumeration;
import ilog.views.IlvGraphicVector;
import ilog.views.IlvManager;
import ilog.views.IlvManagerView;
import ilog.views.IlvPoint;
import ilog.views.IlvRect;
import ilog.views.graphic.IlvArc;
import ilog.views.graphic.IlvArrowLine;
import ilog.views.graphic.IlvArrowPolyline;
import ilog.views.graphic.IlvCircularScale;
import ilog.views.graphic.IlvEllipse;
import ilog.views.graphic.IlvFilledLabel;
import ilog.views.graphic.IlvFullZoomingGraphic;
import ilog.views.graphic.IlvGeneralPath;
import ilog.views.graphic.IlvGraphicSet;
import ilog.views.graphic.IlvIcon;
import ilog.views.graphic.IlvLabel;
import ilog.views.graphic.IlvLine;
import ilog.views.graphic.IlvMarker;
import ilog.views.graphic.IlvPolygon;
import ilog.views.graphic.IlvPolyline;
import ilog.views.graphic.IlvRectangle;
import ilog.views.graphic.IlvRectangularScale;
import ilog.views.graphic.IlvReliefLabel;
import ilog.views.graphic.IlvReliefRectangle;
import ilog.views.graphic.IlvShadowLabel;
import ilog.views.graphic.IlvShadowRectangle;
import ilog.views.graphic.IlvSpline;
import ilog.views.graphic.IlvText;
import ilog.views.graphic.IlvZoomableLabel;
import ilog.views.interactor.IlvSelectInteractor;
import ilog.views.swing.IlvJComponentGraphic;
import ilog.views.swing.IlvJManagerViewControlBar;
import ilog.views.swing.IlvJScrollManagerView;

/**
 * Displays JViews graphics objects that are created using <code>new</code>. Most
 * of the JViews examples read graphics from JViews .ivl files because it makes
 * the code more readable. This example demonstrates the creation of
 * JViews graphics classes in Java code. An example is provided for most of the
 * fundamental JViews graphics types. Furthermore, one type used here,
 * <code>MyZoomableReliefLabel</code>, demonstrates how to create a custom graphic by
 * extending an existing JViews graphic class.
 */
SuppressWarnings("serial")
public class NewGraphics extends JRootPane implements ActionListener {

  /**
   * Some primitives for creating the graphic objects. These are
   * initialized in <code>initPositionData()</code> and used in 
   * <code>addGraphicObjects()</code>.
   */
  public static final int DEFAULT_X = 25;
  public static final int DEFAULT_X_NAMES = 130;
  public static final int VERT_SPACING = 45;
  public static final int DEFAULT_WIDTH = 70;
  public static final int DEFAULT_HEIGHT = 30;

  private IlvPoint ptCenter = new IlvPoint();
  private IlvPoint ptLabel = new IlvPoint();
  private IlvPoint ptUpperLeft = new IlvPoint();
  private IlvPoint ptLowerLeft = new IlvPoint();
  private IlvRect rectBorder = new IlvRect();
  private IlvPoint[] points = new IlvPoint[6];
  private String[] SCALE_LABELS = new String[6];

  /**
   *  A counter for the <code>JButton</code>.
   */
  public int ctr = 1;

  /**
   * The JViews manager.
   */
  private IlvManager manager;

  /**
   * One view of the manager.
   */
  private IlvManagerView mgrview;

  /**
   * Initializes the sample.
   */
  public void init() {

    // 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 the manager.
    manager = new IlvManager();
    // Create the view for the manager.
    mgrview = new IlvManagerView(manager);
    mgrview.setAntialiasing(true);
    // Avoid having a distorted view.
    mgrview.setKeepingAspectRatio(true);
    // Set the background of the view.
    mgrview.setBackground(Color.white);

    addGraphicObjects(0);
    // addFullZoomingGraphicObjects();

    IlvJScrollManagerView scrollview = new IlvJScrollManagerView(mgrview);
    mgrview.setWheelZoomingEnabled(true);
    scrollview.setWheelScrollingEnabled(true);

    getContentPane().add(scrollview, BorderLayout.CENTER);
    // Create a toolbar for basic zoom/unzoom operations.
    IlvJManagerViewControlBar toolbar = new IlvJManagerViewControlBar();
    toolbar.setFloatable(false);
    toolbar.setOrientation(JToolBar.HORIZONTAL);
    toolbar.setView(mgrview);
    ((IlvSelectInteractor) toolbar.getSelectInteractor()).setOpaqueMove(true);
    getContentPane().add(toolbar, BorderLayout.NORTH);
  }

  /**
   * Adds one of each JViews graphic type to the manager.
   */
  public void addGraphicObjects(int deltaX) {
    initPositionData(deltaX);
    // A bitmap.
    IlvIcon icon = null;
    try {
      icon =
          new IlvIcon(ilog.views.util.IlvImageUtil.getImageFromFile(NewGraphics.class, "logos.gif"),
              rectBorder);
    } catch (java.io.IOException e) {
      e.printStackTrace();
    }
    manager.addObject(icon, false);
    addLabel("IlvIcon");

    // A graphic composed of other JViews graphics.
    movePositionData();
    IlvGraphicSet composite = new IlvGraphicSet();
    IlvReliefRectangle border = new IlvReliefRectangle(rectBorder);
    border.setBackground(Color.white);
    int edge = border.getThickness();
    border.moveResize(new IlvRect(rectBorder.x - (4 + edge), rectBorder.y - (4 + edge),
        rectBorder.width + 8 + 2 * edge, rectBorder.height + 8 + 2 * edge));
    composite.addObject(border, false);
    try {
      icon =
          new IlvIcon(ilog.views.util.IlvImageUtil.getImageFromFile(NewGraphics.class, "small.gif"),
              rectBorder);
    } catch (java.io.IOException e) {
    }
    composite.addObject(icon, false);
    IlvPoint ptText = new IlvPoint(ptLowerLeft);
    ptText.translate(0, -15);
    IlvZoomableLabel lbl1 = new IlvZoomableLabel(ptText, "RogueWave");
    Font font = new Font(lbl1.getFont().getName(), Font.BOLD, lbl1.getFont().getSize());
    lbl1.setFont(font);
    composite.addObject(lbl1, false);
    ptText.translate(0, +20);
    IlvZoomableLabel lbl2 = new IlvZoomableLabel(ptText, "JViews");
    lbl2.setFont(font);
    composite.addObject(lbl2, false);
    manager.addObject(composite, false); // false => do not redraw yet.
    addLabel("IlvGraphicSet");

    // A custom graphic class.
    movePositionData();
    MyZoomableReliefLabel custom = new MyZoomableReliefLabel(ptCenter, "Custom\nGraphic");
    custom.setBackground(Color.pink);
    manager.addObject(custom, false); // false => do not redraw yet.
    addLabel("MyZoomableReliefLabel");

    // A rectangle.
    movePositionData();
    IlvRectangle rectangle = new IlvRectangle(rectBorder);
    manager.addObject(rectangle, false);
    addLabel("IlvRectangle");

    // A relief rectangle.
    movePositionData();
    IlvReliefRectangle rlfrect = new IlvReliefRectangle(rectBorder);
    rlfrect.setBackground(Color.cyan);
    manager.addObject(rlfrect, false);
    addLabel("IlvReliefRectangle");

    // A relief label.
    movePositionData();
    IlvReliefLabel rlflbl = new IlvReliefLabel(rectBorder, "Text");
    rlflbl.setBackground(Color.yellow);
    manager.addObject(rlflbl, false);
    addLabel("IlvReliefLabel");

    // A shadow rectangle.
    movePositionData();
    IlvShadowRectangle shdwrect = new IlvShadowRectangle(rectBorder);
    shdwrect.setBackground(Color.red);
    manager.addObject(shdwrect, false);
    addLabel("IlvShadowRectangle");

    // A shadow label.
    movePositionData();
    IlvShadowLabel shdwlbl = new IlvShadowLabel(rectBorder, "Text", 3, IlvDirection.BottomRight);
    shdwlbl.setBackground(Color.green);
    manager.addObject(shdwlbl, false);
    addLabel("IlvShadowLabel");

    // An ellipse.
    movePositionData();
    IlvEllipse ellipse = new IlvEllipse(rectBorder);
    manager.addObject(ellipse, false);
    addLabel("IlvEllipse");

    // An arc.
    movePositionData();
    IlvArc arc = new IlvArc(rectBorder, 90, 205);
    manager.addObject(arc, false);
    addLabel("IlvArc");

    // A filled polygon.
    movePositionData();
    IlvPolygon polygon = new IlvPolygon(points);
    polygon.setForeground(Color.green);
    manager.addObject(polygon, false);
    addLabel("IlvPolygon ");

    // A polyline.
    movePositionData();
    IlvPolyline polyline = new IlvPolyline(points);
    manager.addObject(polyline, false);
    addLabel("IlvPolyline");

    // An arrow ployline.
    movePositionData();
    IlvArrowPolyline apl = new IlvArrowPolyline(points);
    manager.addObject(apl, false);
    addLabel("IlvArrowPolyline");

    // A spline.
    movePositionData();
    IlvSpline spline = new IlvSpline(points);
    manager.addObject(spline, false);
    addLabel("IlvSpline");

    // A filled label.
    movePositionData();
    IlvFilledLabel fLabel = new IlvFilledLabel(ptCenter, "Some Text");
    fLabel.setBackground(Color.yellow);
    manager.addObject(fLabel, false);
    addLabel("IlvFilledLabel");

    // Non-zoomable text.
    movePositionData();
    IlvLabel label = new IlvLabel(ptCenter, "More Text");
    manager.addObject(label, false); // false => do not redraw yet.
    addLabel("IlvLabel");

    // Zoomable text.
    movePositionData();
    IlvZoomableLabel zlabel = new IlvZoomableLabel(ptLowerLeft, "Zoom in!");
    manager.addObject(zlabel, false); // false => do not redraw yet.
    addLabel("IlvZoomableLabel");

    // multi-line text with word wrap.
    movePositionData();
    IlvText tlabel = new IlvText(ptLowerLeft, "Multi-line text");
    tlabel.setWrappingWidth(rectBorder.width);
    tlabel.setWrappingMode(IlvText.WRAP_WORD);
    manager.addObject(tlabel, false); // false => do not redraw yet.
    addLabel("IlvText");


    // A non-zooming marker.
    movePositionData();
    IlvMarker marker = new IlvMarker(ptCenter, IlvMarker.IlvMarkerFilledDiamond);
    marker.setForeground(Color.cyan);
    manager.addObject(marker, false); // false => do not redraw yet.
    addLabel("IlvMarker");

    // A simple line.
    movePositionData();
    IlvLine line = new IlvLine(rectBorder.x, rectBorder.y, rectBorder.x + rectBorder.width,
        rectBorder.y + rectBorder.height);
    manager.addObject(line, false); // false => do not redraw yet.
    addLabel("IlvLine");

    // An arrow line.
    movePositionData();
    IlvArrowLine aline = new IlvArrowLine(rectBorder.x, rectBorder.y + rectBorder.height,
        rectBorder.x + rectBorder.width, rectBorder.y, 1.0);
    manager.addObject(aline, false); // false => do not redraw yet.
    addLabel("IlvArrowLine");

    // A linear scale.
    movePositionData();
    IlvRectangularScale scale = new IlvRectangularScale(ptUpperLeft, DEFAULT_WIDTH, SCALE_LABELS, 5,
        IlvDirection.Left, IlvDirection.Bottom, 10, 2);
    manager.addObject(scale, false); // false => do not redraw yet.
    addLabel("IlvRectangularScale");

    // A circular scale.
    movePositionData();
    IlvRect scalerect = new IlvRect(rectBorder);
    scalerect.height = scalerect.width;
    scalerect.translate(0, 20);
    IlvCircularScale cscale =
        new IlvCircularScale(scalerect, SCALE_LABELS, 90, 360, false, 5, 10, 2);
    manager.addObject(cscale, false); // false => do not redraw yet.
    addLabel("IlvCircularScale");
    movePositionData(); // The scale is quite big so move further.
    movePositionData();

    // A Swing component wrapped in a JViews graphic.
    movePositionData();
    JButton jbtn = new JButton("Go");
    jbtn.addActionListener(this);
    IlvJComponentGraphic jcomp = new IlvJComponentGraphic(rectBorder, jbtn);
    manager.addObject(jcomp, false); // false => do not redraw yet.
    addLabel("IlvJComponentGraphic");

    // A Java 2D shape object with a gradient fill.
    movePositionData();
    Shape shape =
        new Rectangle2D.Double(ptUpperLeft.x, ptUpperLeft.y, DEFAULT_WIDTH, DEFAULT_HEIGHT);
    IlvGeneralPath path = new IlvGeneralPath(shape);
    path.setFillPaint(new GradientPaint(
        new Point((int) ptUpperLeft.x + DEFAULT_WIDTH / 2, (int) ptUpperLeft.y), Color.yellow,
        new Point((int) ptUpperLeft.x + DEFAULT_WIDTH / 2, (int) ptUpperLeft.y + DEFAULT_HEIGHT),
        Color.red));
    manager.addObject(path, false);
    addLabel("IlvGeneralPath");
  }

  /**
   * Adds one of each JViews graphic type to the manager.
   * This is the same as previous method, except that this time, we encapsulate
   * each graphic in a IlvFullZoomingGraphic with transparency.
   * <p>
   * IlvFullZoomingGraphic if you need to make a nonzoomable object zoomable,
   * of if you want to add transparency to an object.
   * <p>
   * This method is currently not used in this sample. Uncomment the call
   * of this method inside init to see the effect of this method.
   */
  public void addFullZoomingGraphicObjects() {
    double initZoom = 1;
    float alpha = 0.3f;
    IlvFullZoomingGraphic fzg;

    addGraphicObjects(300);

    IlvGraphicVector v = new IlvGraphicVector();
    IlvGraphicEnumeration e = manager.getObjects();
    while (e.hasMoreElements()) {
      IlvGraphic g = e.nextElement();
      // cannot wrap IlvJComponentGraphic into any graphic handle
      if (g.boundingBox().x >= 300 && !(g instanceof IlvJComponentGraphic))
        v.addElement(g);
    }

    e = v.elements();
    while (e.hasMoreElements()) {
      IlvGraphic g = e.nextElement();
      IlvRect bbox = g.boundingBox();
      manager.removeObject(g, false);
      fzg = new IlvFullZoomingGraphic(g, initZoom);
      fzg.setAlpha(alpha);
      fzg.move(bbox.x, bbox.y);
      manager.addObject(fzg, false);
    }

    ptLabel.x = 300;
    ptLabel.y = -10;
    addLabel("Objects wrapped in IlvFullZoomingGraphic");
  }

  /**
   * Adds a non-zoomable label to the right of the current graphic object's
   * position.
   */
  public void addLabel(String text) {
    IlvZoomableLabel lbl = new IlvZoomableLabel(ptLabel, text);
    manager.addObject(lbl, false);
  }


  /**
   * Creates the points and rectangles used to create new graphics. This way
   * the graphic creation code is not cluttered with several position
   * calculations.
   */
  private void initPositionData(int deltaX) {
    int x = DEFAULT_X + deltaX;
    int w = DEFAULT_WIDTH;
    int y = VERT_SPACING / 2;
    int h = DEFAULT_HEIGHT;
    ptCenter.move(x + w / 2, y);
    ptLabel.move(DEFAULT_X_NAMES + deltaX, h + 5);
    rectBorder.reshape(x, (VERT_SPACING - h) / 2, w, h);
    ptUpperLeft.move(x, y - h / 2);
    ptLowerLeft.move(x, y + y / 2);
    //// Creation of an array of points that describes a star.
    // upper-left
    points[0] = new IlvPoint(x, y + h / 3);
    // upper-right
    points[1] = new IlvPoint(x + w, y + h / 3);
    // lower-left
    points[2] = new IlvPoint(x + w / 5, y + h);
    // top-center
    points[3] = new IlvPoint(x + w / 2, y);
    // lower-right
    points[4] = new IlvPoint(x + 4 * w / 5, y + h);
    // upper-left
    points[5] = new IlvPoint(points[0]);
    // Labels for the scales.
    SCALE_LABELS[0] = new String();
    for (int i = 1; i < SCALE_LABELS.length; i++) {
      SCALE_LABELS[i] = String.valueOf(i);
    }
  }

  /**
   * Moves the points and rectangles used to create new graphics. This is
   * called before creating each graphic above. This way the graphic creation
   * code is not cluttered with several position calculations.
   */
  private void movePositionData() {
    ptLabel.translate(0, VERT_SPACING);
    ptCenter.translate(0, VERT_SPACING);
    ptUpperLeft.translate(0, VERT_SPACING);
    ptLowerLeft.translate(0, VERT_SPACING);
    rectBorder.translate(0, VERT_SPACING);
    for (int i = 0; i < points.length; i++) {
      points[i].translate(0, VERT_SPACING);
    }
  }

  /**
   * Handler for the embedded <code>JButton</code>.
   */
  Override
  public void actionPerformed(ActionEvent event) {
    ((JButton) event.getSource()).setText(String.valueOf(ctr++));
  }

  /**
   * A main method to run the demo as an application.
   */
  public static void main(String[] args) {
    // Sun recommends that to put the entire GUI initialization into the
    // AWT thread
    SwingUtilities.invokeLater(new Runnable() {
      Override
      public void run() {
        JFrame frame = new JFrame("Creation of IlvGraphic's");
        frame.addWindowListener(new WindowAdapter() {
          Override
          public void windowClosing(WindowEvent e) {
            System.exit(0);
          }
        });
        NewGraphics app = new NewGraphics();
        frame.getContentPane().add(app);
        frame.setSize(300, 600);
        app.init();
        frame.setVisible(true);
      }
    });
  }
}