/*
 * RenderFrame.java
 *
 * Created on 07 August 2001, 14:12
 */

import java.util.*;
import java.io.*;
import javax.swing.*;

import java.awt.*;
import java.awt.event.*;

import com.sun.j3d.utils.geometry.*;
import javax.vecmath.*;
import javax.media.j3d.*;
/**
 *
 * @author  dymaxion
 * @version
 */
public class RenderFrame extends JFrame implements ActionListener {
    public RenderFrame() {
        this(null);
    }

    /** Creates new form RenderFrame */
    public RenderFrame(File f) {
        initComponents();
        // load render objects from file / directory f
        pack();

        // create layer menu
        layerMenuItems = new JCheckBoxMenuItem[MAX_LAYERS];

        for (int i = 0; i < MAX_LAYERS; i++) {
            layerMenuItems[i] = new JCheckBoxMenuItem();
            layerMenuItems[i].setText("Layer " + (i+1));
            layerMenuItems[i].addActionListener(this);
            windowMenu.add(layerMenuItems[i]);
        }
        setLayerMenu(1);
        layerButton.addActionListener(this);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the FormEditor.
     */
    private void initComponents() {//GEN-BEGIN:initComponents
            mainMenuBar = new javax.swing.JMenuBar();
            fileMenu = new javax.swing.JMenu();
            openMenuItem = new javax.swing.JMenuItem();
            saveMenuItem = new javax.swing.JMenuItem();
            saveAsMenuItem = new javax.swing.JMenuItem();
            saveAllMenuItem = new javax.swing.JMenuItem();
            jSeparator1 = new javax.swing.JSeparator();
            prefMenuItem = new javax.swing.JMenuItem();
            jSeparator3 = new javax.swing.JSeparator();
            exitMenuItem = new javax.swing.JMenuItem();
            navigateMenu = new javax.swing.JMenu();
            prevMenuItem = new javax.swing.JMenuItem();
            nextMenuItem = new javax.swing.JMenuItem();
            refreshMenuItem = new javax.swing.JMenuItem();
            jSeparator2 = new javax.swing.JSeparator();
            homeMenuItem = new javax.swing.JMenuItem();
            windowMenu = new javax.swing.JMenu();
            tileSquareMenuItem = new javax.swing.JMenuItem();
            tileRectMenuItem = new javax.swing.JMenuItem();
            jSeparator5 = new javax.swing.JSeparator();
            helpMenu = new javax.swing.JMenu();
            aboutMenuItem = new javax.swing.JMenuItem();
            jDesktopPane = new javax.swing.JDesktopPane();
            mainToolBar = new javax.swing.JToolBar();
            openButton = new javax.swing.JButton();
            saveButton = new javax.swing.JButton();
            saveAllButton = new javax.swing.JButton();
            backButton = new javax.swing.JButton();
            layerTextField = new javax.swing.JTextField();
            nextButton = new javax.swing.JButton();
            layerButton = new javax.swing.JButton();
            homeButton = new javax.swing.JButton();
            prefButton = new javax.swing.JButton();

            fileMenu.setText("File");
            openMenuItem.setText("Open...");
            openMenuItem.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    openAction(evt);
                }
            });

            fileMenu.add(openMenuItem);
            saveMenuItem.setText("Save");
            saveMenuItem.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    saveActionPerformed(evt);
                }
            });

            fileMenu.add(saveMenuItem);
            saveAsMenuItem.setText("Save As...");
            saveAsMenuItem.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    saveAs(evt);
                }
            });

            fileMenu.add(saveAsMenuItem);
            saveAllMenuItem.setText("Save All");
            fileMenu.add(saveAllMenuItem);
            fileMenu.add(jSeparator1);
            prefMenuItem.setText("Preferences...");
            prefMenuItem.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    preferencesActionPerformed(evt);
                }
            });

            fileMenu.add(prefMenuItem);
            fileMenu.add(jSeparator3);
            exitMenuItem.setText("Exit");
            exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    exitMenuItemActionPerformed(evt);
                }
            });

            fileMenu.add(exitMenuItem);
            mainMenuBar.add(fileMenu);
          navigateMenu.setText("Navigate");
            prevMenuItem.setText("Previous Layer");
            prevMenuItem.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    previousLayerAction(evt);
                }
            });

            navigateMenu.add(prevMenuItem);
            nextMenuItem.setText("Next Layer");
            nextMenuItem.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    nextLayerAction(evt);
                }
            });

            navigateMenu.add(nextMenuItem);
            refreshMenuItem.setText("Refresh Layers");
            navigateMenu.add(refreshMenuItem);
            navigateMenu.add(jSeparator2);
            homeMenuItem.setText("Home");
            homeMenuItem.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    gotoHomeAction(evt);
                }
            });

            navigateMenu.add(homeMenuItem);
            mainMenuBar.add(navigateMenu);
          windowMenu.setText("Window");
            tileSquareMenuItem.setText("Tile Square");
            tileSquareMenuItem.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    tileSquareMenuItemActionPerformed(evt);
                }
            });

            windowMenu.add(tileSquareMenuItem);
            tileRectMenuItem.setText("Tile Rectangular");
            tileRectMenuItem.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    tileRectMenuItemActionPerformed(evt);
                }
            });

            windowMenu.add(tileRectMenuItem);
            windowMenu.add(jSeparator5);
            mainMenuBar.add(windowMenu);
          helpMenu.setText("Help");
            aboutMenuItem.setText("About");
            aboutMenuItem.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    aboutMenuItemActionPerformed(evt);
                }
            });

            helpMenu.add(aboutMenuItem);
            mainMenuBar.add(helpMenu);

          addWindowListener(new java.awt.event.WindowAdapter() {
              public void windowClosing(java.awt.event.WindowEvent evt) {
                  exitForm(evt);
              }
          });

          jDesktopPane.setPreferredSize(new java.awt.Dimension(400, 300));
          getContentPane().add(jDesktopPane, java.awt.BorderLayout.CENTER);

        setJMenuBar(mainMenuBar);
    }//GEN-END:initComponents

    private void tileRectMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tileRectMenuItemActionPerformed
        tileLayer(false);
    }//GEN-LAST:event_tileRectMenuItemActionPerformed

    private void tileSquareMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tileSquareMenuItemActionPerformed
        tileLayer(true);
    }//GEN-LAST:event_tileSquareMenuItemActionPerformed

  private void gotoHomeAction(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gotoHomeAction
      // editied out
  }//GEN-LAST:event_gotoHomeAction

  private void layerSetVisible(boolean isVisible, int layer, boolean singleLayer) {
      Iterator i = organixStore.iterator();
      while (i.hasNext()) {
          Canvas3DintFrame intFrame = (Canvas3DintFrame)i.next();
          try {
              if (intFrame.getLayer() == layer) {
                  if (!isVisible) {
                      intFrame.setIcon(false);
                  }
                  intFrame.setVisible(isVisible);
              }
              else if (singleLayer) {
                  intFrame.setIcon(false);
                  intFrame.setVisible(!isVisible);
              }
          } catch (java.beans.PropertyVetoException e) {
          }
      }
  }

  private void setLayerMenu(int layer) {
      for (int i=0; i < MAX_LAYERS; i++) {
          layerMenuItems[i].setSelected(false);
      }
      layerMenuItems[layer-1].setSelected(true);
  }

  private void previousLayerAction(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_previousLayerAction
      int currentLayer = Integer.parseInt(layerTextField.getText());
      if (currentLayer > 1) {
          layerTextField.setText(Integer.toString(--currentLayer));
          layerSetVisible(true, currentLayer, true);
          setLayerMenu(currentLayer);
      }
  }//GEN-LAST:event_previousLayerAction

  private void nextLayerAction(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextLayerAction
      int currentLayer = Integer.parseInt(layerTextField.getText());
      if (currentLayer < MAX_LAYERS) {
          layerTextField.setText(Integer.toString(++currentLayer));
          layerSetVisible(true, currentLayer, true);
          setLayerMenu(currentLayer);
      }
  }//GEN-LAST:event_nextLayerAction

  private void saveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveActionPerformed
  }//GEN-LAST:event_saveActionPerformed

  private void saveAs(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveAs
  }//GEN-LAST:event_saveAs

  private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuItemActionPerformed
      System.exit(0);
  }//GEN-LAST:event_exitMenuItemActionPerformed

  private void openAction(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openAction
      for (int loop=0; loop < 4; loop++) {
          Canvas3DintFrame displayFrame = new Canvas3DintFrame("Test Organix", this);

          Group world = displayFrame.getWorld();
          createOrganix(world);

          displayFrame.makeLive();
          displayFrame.setVisible(true);
          displayFrame.setSize(200,200);
          organixStore.add(displayFrame);
          jDesktopPane.add(displayFrame);
      }

  }//GEN-LAST:event_openAction

  private void aboutMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_aboutMenuItemActionPerformed
  }//GEN-LAST:event_aboutMenuItemActionPerformed

  private void preferencesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_preferencesActionPerformed
  }//GEN-LAST:event_preferencesActionPerformed

  private void tileLayer(boolean square) {
      Dimension deskSize = jDesktopPane.getSize();

      // get number of active frames
      ArrayList activeFrames = new ArrayList();
      for (int loop = 0; loop < organixStore.size(); loop++) {
          Canvas3DintFrame frame = (Canvas3DintFrame)organixStore.get(loop);
          if (frame.isVisible() && !frame.isIcon())
              activeFrames.add(frame);
      }
      float numFrames = (float)activeFrames.size();

      // determine how many rows and cols we need
      float cols = 1, rows = 1;
      while (cols * rows < numFrames) {
          float paneAspectRatio = deskSize.width / deskSize.height;
          if (cols / rows < paneAspectRatio)
              cols++;
          else
              rows++;
      }
      int width = Math.round(deskSize.width / cols);
      int height = Math.round(deskSize.height / rows);
      int length = Math.min(width, height);

      // reduce rows and see if size is better
      float rowsB = rows - 1;
      float colsB = (float)Math.ceil((double)(numFrames / rowsB));
      int heightB = Math.round(deskSize.height / rowsB);
      int widthB = Math.round(deskSize.width/ colsB);
      int lengthB = Math.min(widthB, heightB);

      // check optimal sizes
      if (lengthB > length) {
          cols = colsB;
          rows = rowsB;
          width = widthB;
          height = heightB;
          length = lengthB;
      }
      if (square) {
          width = length;
          height = length;
      }
      // arrange the windows now
      for (int counter = 0; counter < activeFrames.size(); counter++) {
          Canvas3DintFrame intFrame = (Canvas3DintFrame)activeFrames.get(counter);
          int xpos = counter % (int)cols;
          int ypos = counter / (int)cols;

          intFrame.setSize(width, height);
          intFrame.setLocation(width * xpos, height * ypos);
      }
  }

  private void createOrganix(Group objRoot) {
      Transform3D transform = new Transform3D();
      Appearance app = createAppearance();

      for (int i=0, total = 40; i < total; i++) {
          transform.setTranslation(new Vector3f((float)Math.sin(i*4*Math.PI / total), (float)Math.cos(i*4*Math.PI / (total)), (float)Math.cos(i*2*Math.PI / (total))));
          TransformGroup transGroup = new TransformGroup(transform);
          Sphere blob = new Sphere(0.3f, Sphere.GENERATE_TEXTURE_COORDS |
          Sphere.GENERATE_NORMALS, 20, app);

          transGroup.addChild(blob);
          objRoot.addChild(transGroup);
      }
  }

  private Appearance createAppearance() {
      Appearance appearance = new Appearance();
      Material material = new Material();
      Color3f sphAmbColor = null;
      Color3f sphDifColor = null;

      sphereColor = ++sphereColor % 3;
      if (sphereColor == 0) {
          sphDifColor = new Color3f(1.0f, 0.0f, 0.0f);
          sphAmbColor = new Color3f(0.3f, 0.0f, 0.0f);
      } else if (sphereColor == 1) {
          sphDifColor = new Color3f(0.0f, 1.0f, 0.0f);
          sphAmbColor = new Color3f(0.0f, 0.3f, 0.0f);
      } else if (sphereColor == 2) {
          sphDifColor = new Color3f(0.0f, 0.0f, 1.0f);
          sphAmbColor = new Color3f(0.0f, 0.0f, 0.3f);
      }

      material.setAmbientColor(sphAmbColor);
      material.setDiffuseColor(sphDifColor);
      material.setEmissiveColor(new Color3f(0.2f, 0.2f, 0.2f));
      material.setSpecularColor(new Color3f(1.0f, 1.0f, 1.0f));
      material.setShininess(100.0f);
      appearance.setMaterial(material);
      return(appearance);
  }

  /** Exit the Application */
    private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm
        System.exit(0);
    }//GEN-LAST:event_exitForm

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        new RenderFrame().setVisible(true);
    }

    public void actionPerformed(java.awt.event.ActionEvent evt) {
        for (int i = 0; i < layerMenuItems.length; i++) {
            layerSetVisible(layerMenuItems[i].isSelected(), (i+1), false);
        }
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuBar mainMenuBar;
    private javax.swing.JMenu fileMenu;
    private javax.swing.JMenuItem openMenuItem;
    private javax.swing.JMenuItem saveMenuItem;
    private javax.swing.JMenuItem saveAsMenuItem;
    private javax.swing.JMenuItem saveAllMenuItem;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JMenuItem prefMenuItem;
    private javax.swing.JSeparator jSeparator3;
    private javax.swing.JMenuItem exitMenuItem;
    private javax.swing.JMenu navigateMenu;
    private javax.swing.JMenuItem prevMenuItem;
    private javax.swing.JMenuItem nextMenuItem;
    private javax.swing.JMenuItem refreshMenuItem;
    private javax.swing.JSeparator jSeparator2;
    private javax.swing.JMenuItem homeMenuItem;
    private javax.swing.JMenu windowMenu;
    private javax.swing.JMenuItem tileSquareMenuItem;
    private javax.swing.JMenuItem tileRectMenuItem;
    private javax.swing.JSeparator jSeparator5;
    private javax.swing.JMenu helpMenu;
    private javax.swing.JMenuItem aboutMenuItem;
    private javax.swing.JDesktopPane jDesktopPane;
    private javax.swing.JToolBar mainToolBar;
    private javax.swing.JButton openButton;
    private javax.swing.JButton saveButton;
    private javax.swing.JButton saveAllButton;
    private javax.swing.JButton backButton;
    private javax.swing.JTextField layerTextField;
    private javax.swing.JButton nextButton;
    private javax.swing.JButton layerButton;
    private javax.swing.JButton homeButton;
    private javax.swing.JButton prefButton;
    // End of variables declaration//GEN-END:variables

    protected static final int MAX_LAYERS = 7;
    private ArrayList organixStore = new ArrayList();
    private JCheckBoxMenuItem[] layerMenuItems;
    // remove later
    static int sphereColor = 0;
}
