
// Loader3D.java
// Andrew Davison, April 2005, ad@fivedots.coe.psu.ac.th

/* Načte objekt do šachovnicového světa a upraví jej tak,
   aby jeho ohraničující koule měla poloměr 1. Modely 3ds
   dále otočí o -90 stupňů kolem osy x.
   Používá načítací rutiny knihovny Portfolio.

   Tato třída má na starosti GUI pro pohyby, rotace a změny měřítka.
   GUI dále obsahuje tlačítko pro uložení dat o poloze modelu do 
   konfiguračního souboru.

   Jakmile je objekt načten, lze k němu načíst také příslušný konfigurační
   soubor, vytvoření při dřívějším spušťení.
*/

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.text.DecimalFormat;
import java.io.*;

import javax.vecmath.*;


public class Loader3D extends JFrame implements ActionListener
{
  // pro specifikaci pohybů a rotací
  private static final int X_AXIS = 0;
  private static final int Y_AXIS = 1;
  private static final int Z_AXIS = 2;
  private static final int INCR = 0;
  private static final int DECR = 1;

  private WrapLoader3D w3d;    // J3D-canvas pro načítací rutiny

  // prvky GUI
  private JButton xPosLeftBut, xPosRightBut, yPosLeftBut, yPosRightBut, zPosLeftBut, zPosRightBut;
  private JButton xRotLeftBut, xRotRightBut, yRotLeftBut, yRotRightBut, zRotLeftBut, zRotRightBut;
  private JTextField scaleTF;
  private JTextField xyzTF, rotTF, scaleTotTF;
  private JButton saveBut;

  private DecimalFormat df;    // pro výstup textfield



  public Loader3D(String args[]) 
  {
    super("3D Loader");

    boolean hasCoordsInfo = false;
    String filename = null;
    if ((args.length == 2) && (args[0].equals("-c"))) {
      hasCoordsInfo = true;
      filename = args[1];
    }
    else if (args.length == 1) 
       filename = args[0];       
    else {
      System.out.println( "Použití: java Loader3D [-c] <file>");
      System.exit(0);
    }

    w3d = new WrapLoader3D(filename, hasCoordsInfo);
    initGUI();

    setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    pack();
    setResizable(false);    // rozměry okna jsou pevně dány
    setVisible(true);
  } // konec metody: Loader3D()



  private void initGUI()
  /* GUI má uprostřed 3D-canvas, dále obsahuje sloupec tlačítek, textových
     polí a dalších prvků vyplňující panel až k pravé dolní straně (řídící
     panel).
     Horní polovina řídícího panelu slouží pro zadávání dat: řada tlačítek
     provádějících pohyby a rotace a textové pole pro zadávání měřítka.
     Spodní polovina panelu je pro zobrazování údajů o aktuální pozici, 
     rotaci a měřítku.
  */
  {
    ImageIcon upIcon = new ImageIcon("icons/up.gif");
    ImageIcon downIcon = new ImageIcon("icons/down.gif");
    ImageIcon leftIcon = new ImageIcon("icons/left.gif");
    ImageIcon rightIcon = new ImageIcon("icons/right.gif");
    ImageIcon inIcon = new ImageIcon("icons/in.gif");
    ImageIcon outIcon = new ImageIcon("icons/out.gif");

    df = new DecimalFormat("0.###");  // 3 dm

    Container c = getContentPane();
    c.setLayout( new BorderLayout() );
    c.add(w3d, BorderLayout.CENTER);

    // sestav vstupní ovládací prvky

    JPanel p1 = new JPanel();
    JLabel xPosLabel = new JLabel("Posun podél X:");
    xPosLeftBut = new JButton(leftIcon);
    xPosLeftBut.addActionListener(this);
    xPosRightBut = new JButton(rightIcon);
    xPosRightBut.addActionListener(this);
    p1.add(xPosLabel); p1.add(xPosLeftBut); p1.add(xPosRightBut);

    JPanel p2 = new JPanel();
    JLabel yPosLabel = new JLabel("Posun podél Y:");
    yPosLeftBut = new JButton(downIcon);
    yPosLeftBut.addActionListener(this);
    yPosRightBut = new JButton(upIcon);
    yPosRightBut.addActionListener(this);
    p2.add(yPosLabel); p2.add(yPosLeftBut); p2.add(yPosRightBut);

    JPanel p3 = new JPanel();
    JLabel zPosLabel = new JLabel("Posun podél Z:");
    zPosLeftBut = new JButton(inIcon);
    zPosLeftBut.addActionListener(this);
    zPosRightBut = new JButton(outIcon);
    zPosRightBut.addActionListener(this);
    p3.add(zPosLabel); p3.add(zPosLeftBut); p3.add(zPosRightBut);

    JPanel p4 = new JPanel();
    JLabel xRotLabel = new JLabel("Rotace kolem X:");
    xRotLeftBut = new JButton(leftIcon);
    xRotLeftBut.addActionListener(this);
    xRotRightBut = new JButton(rightIcon);
    xRotRightBut.addActionListener(this);
    p4.add(xRotLabel); p4.add(xRotLeftBut); p4.add(xRotRightBut);

    JPanel p5 = new JPanel();
    JLabel yRotLabel = new JLabel("Rotace kolem Y:");
    yRotLeftBut = new JButton(leftIcon);
    yRotLeftBut.addActionListener(this);
    yRotRightBut = new JButton(rightIcon);
    yRotRightBut.addActionListener(this);
    p5.add(yRotLabel); p5.add(yRotLeftBut); p5.add(yRotRightBut);


    JPanel p6 = new JPanel();
    JLabel zRotLabel = new JLabel("Rotace kolem Z:");
    zRotLeftBut = new JButton(leftIcon);
    zRotLeftBut.addActionListener(this);
    zRotRightBut = new JButton(rightIcon);
    zRotRightBut.addActionListener(this);
    p6.add(zRotLabel); p6.add(zRotLeftBut); p6.add(zRotRightBut);

    JPanel p7 = new JPanel();
    JLabel scaleLabel = new JLabel("Vynásob měřítko:");
    scaleTF = new JTextField("1.1", 4);
    scaleTF.addActionListener(this);
    p7.add(scaleLabel); p7.add(scaleTF);

    JPanel p8 = new JPanel();
    saveBut = new JButton("Ulož konfiguraci");
    saveBut.addActionListener(this);
    p8.add(saveBut);

    // sestav ovládací prvky pro hlášení údajů

    JLabel xyzLabel = new JLabel("Pozice (x,y,z):");
    xyzTF = new JTextField(10);
    xyzTF.setEditable(false);

    JLabel rotLabel = new JLabel("Rotace (x,y,z):");
    rotTF = new JTextField(10);
    rotTF.setEditable(false);

    JPanel pScale = new JPanel();
    JLabel scaleTotLabel = new JLabel("Měřítko celkem:");
    scaleTotTF = new JTextField(4);
    scaleTotTF.setEditable(false);
    pScale.add(scaleTotLabel); pScale.add(scaleTotTF);

    // hlavní řídící panel
    JPanel ctrlPanel = new JPanel();
    ctrlPanel.setLayout(
			new BoxLayout(ctrlPanel, BoxLayout.Y_AXIS));
    // přidej vstupní ovládací prvky
    ctrlPanel.add(p1); ctrlPanel.add(p2);
    ctrlPanel.add(p3); ctrlPanel.add(p4);
    ctrlPanel.add(p5); ctrlPanel.add(p6);
    ctrlPanel.add(p7); ctrlPanel.add(p8);

    // přidej kousek prostoru mezi vstupy a výstupy
    ctrlPanel.add( javax.swing.Box.createVerticalStrut(15) );

    // přidej ovládací prvky pro hlášení údaj
    ctrlPanel.add(xyzLabel);
    ctrlPanel.add(xyzTF);
    ctrlPanel.add(rotLabel);
    ctrlPanel.add(rotTF);
    ctrlPanel.add(pScale);

    JPanel ctrlP = new JPanel();
    ctrlP.add(ctrlPanel);

    c.add(ctrlP, BorderLayout.EAST);

    showPosInfo();   // aktualizuj obrazovku
    showRotInfo();
    showScale();
  }  // konec metody: initGUI()



  public void actionPerformed(ActionEvent e)
  {
    if (e.getSource() == saveBut)   // ulož údaje konfigurace modelu
      w3d.saveCoordFile();
    else if (e.getSource() == xPosLeftBut)   // pohyb ve směru X
      w3d.movePos(X_AXIS, DECR);
    else if (e.getSource() == xPosRightBut)
      w3d.movePos(X_AXIS, INCR);
    else if (e.getSource() == yPosLeftBut)   // pohyb ve směru Y
      w3d.movePos(Y_AXIS, DECR);
    else if (e.getSource() == yPosRightBut)
      w3d.movePos(Y_AXIS, INCR);
    else if (e.getSource() == zPosLeftBut)   // pohyb ve směru Z
      w3d.movePos(Z_AXIS, DECR);
    else if (e.getSource() == zPosRightBut)
      w3d.movePos(Z_AXIS, INCR);
    else 
    if (e.getSource() == xRotLeftBut)        // rotace kolem osy X
      w3d.rotate(X_AXIS, DECR);
    else if (e.getSource() == xRotRightBut)
      w3d.rotate(X_AXIS, INCR);
    else if (e.getSource() == yRotLeftBut)   // rotace kolem osy Y
      w3d.rotate(Y_AXIS, INCR);
    else if (e.getSource() == yRotRightBut)
      w3d.rotate(Y_AXIS, DECR);
    else if (e.getSource() == zRotLeftBut)   // rotace kolem osy Z
      w3d.rotate(Z_AXIS, INCR);
    else if (e.getSource() == zRotRightBut)
      w3d.rotate(Z_AXIS, DECR);
    else if (e.getSource() == scaleTF) {   // změna měřítka
      try {
        double d = Double.parseDouble( e.getActionCommand() );
        w3d.scale(d);
      }
      catch(NumberFormatException ex) {
        System.out.println("Změna měřítka musí být číslo");
      }
    }
    showPosInfo();   // aktualizuj obrazovku
    showRotInfo();
    showScale();
  }  // konec metody: actionPerformed()


  private void showPosInfo()
  {  
    Vector3d loc = w3d.getLoc();
    xyzTF.setText("( " + df.format(loc.x) + ", " +
				df.format(loc.y) + ", " + df.format(loc.z) + " )");  
  }


  private void showRotInfo()
  {  
     Point3d rots = w3d.getRotations();
     rotTF.setText("( " + df.format(rots.x) + ", " +
				df.format(rots.y) + ", " + df.format(rots.z) + " )");  
  }


  private void showScale()
  { 
    double scale = w3d.getScale();
    scaleTotTF.setText( df.format(scale) );  
  }


// ----------------------------------------

  public static void main(String[] args)
  { new Loader3D(args); }

} // konec třídy: Loader3D class

