/*=========================================================================

  Program:   Orbit Visualization Tool
  Source:    $Source: /stor/devel/ovt2g/ovt/object/OrbitMonitorModule.java,v $
  Date:      $Date: 2001/04/19 17:58:40 $
  Version:   $Revision: 1.32 $


Copyright (c) 2000 OVT Team (Kristof Stasiewicz, Mykola Khotyaintsev, 
Yuri Khotyaintsev)
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification is permitted provided that the following conditions are met:

 * No part of the software can be included in any commercial package without
written consent from the OVT team.

 * Redistributions of the source or binary code must retain the above
copyright notice, this list of conditions and the following disclaimer.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT OR
INDIRECT DAMAGES  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE.

OVT Team (http://ovt.irfu.se)   K. Stasiewicz, M. Khotyaintsev, Y.
Khotyaintsev

=========================================================================*/

package ovt.object;

import ovt.*;
import ovt.gui.*;
import ovt.beans.*;
import ovt.util.*;
import ovt.event.*;
import ovt.datatype.*;
import ovt.interfaces.*;
import ovt.model.magnetopause.*;

import java.beans.*;

import java.io.*;
import java.util.*;
import java.text.DecimalFormat;

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

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;

/**
 * A window, which shows satelite's position, velosity, footprints, etc.
 */ 

public class OrbitMonitorModule extends AbstractSatModule {

  private static final String km = "km";
  private static final String RE = "RE";
  /** format for position, distance */
  private DecimalFormat format = new DecimalFormat();
  /** format for B field */
  private DecimalFormat bFormat = new DecimalFormat();
  /** format for footprints */
  private DecimalFormat footprintFormat = new DecimalFormat();
  /** format for spin */
  private DecimalFormat spinFormat = new DecimalFormat();
  /** format for time */
  private TimeFormat timeFormat = new TimeFormat();
  
  protected JTextField x, y, z, radius, velocity, b, time, dist_to_mpause, spin;
  protected JTextField[] latitude = new JTextField[2];
  protected JTextField[] longitude = new JTextField[2];
  protected JLabel position, footprint;
  protected JFrame orbitMonitor = null;
  private DumpRecord dumpRecord = new DumpRecord();
  private JButton showhideDumperButton;
  private Dumper dumper = new Dumper(this);
  
  /** Holds value of property distanceUnit. */
  private String distanceUnit = "RE";
  /** Holds value of property dumperVisible. */
  private boolean dumperVisible = false;
 
  
public OrbitMonitorModule(Sat sat) {
  super(sat, "OrbitMonitor");
  showInTree(false);
  format.setPositivePrefix(" ");
  format.setMinimumFractionDigits(2);
  format.setMaximumFractionDigits(2);
  // set format for B
  bFormat.setPositivePrefix(" ");
  bFormat.setMinimumFractionDigits(2);
  bFormat.setMaximumFractionDigits(2);
  // format footprints
  footprintFormat.setPositivePrefix(" ");
  footprintFormat.setMinimumFractionDigits(2);
  footprintFormat.setMaximumFractionDigits(2);
  // format spin
  spinFormat.setPositivePrefix(" ");
  spinFormat.setMinimumFractionDigits(2);
  spinFormat.setMaximumFractionDigits(2);
  
  // create descriptors
  try {
        Descriptors descriptors = getDescriptors();
        // distanceUnit
        BasicPropertyDescriptor pd = new BasicPropertyDescriptor("distanceUnit", this);
        pd.setDisplayName("Distance unit");
        pd.setLabel("unit");
        
        String[] values = { RE, km };
        GUIPropertyEditor editor = new ComboBoxPropertyEditor(pd, values, values);
        pd.setPropertyEditor(editor);
        addPropertyChangeListener("distanceUnit", editor);
        descriptors.put(pd);
        
        // distance fraction digits
        pd = new BasicPropertyDescriptor("distanceFractionDigits", this);
        pd.setDisplayName("Distance unit");
        pd.setLabel("unit");
        
        String[] tags = { ".", ".0", ".00", ".000", ".0000" };
        editor = new ComboBoxPropertyEditor(pd, Utils.getIndexes(tags), tags);
        pd.setPropertyEditor(editor);
        addPropertyChangeListener("distanceFractionDigits", editor);
        descriptors.put(pd);
        //pd.setTextOnlyAccessible();
        
        // distance fraction digits
        pd = new BasicPropertyDescriptor("footprintFractionDigits", this);
        editor = new ComboBoxPropertyEditor(pd, Utils.getIndexes(tags), tags);
        pd.setPropertyEditor(editor);
        addPropertyChangeListener("footprintFractionDigits", editor);
        descriptors.put(pd);
        
        // -- Time format :
        // date format
        pd = new BasicPropertyDescriptor("dateFormat", this);
        editor = new ComboBoxPropertyEditor(pd, TimeFormat.getDateFormats(), TimeFormat.getDateFormatNames());
        pd.setPropertyEditor(editor);
        addPropertyChangeListener("dateFormat", editor);
        descriptors.put(pd);
        // hours format
        pd = new BasicPropertyDescriptor("hoursFormat", this);
        editor = new ComboBoxPropertyEditor(pd, TimeFormat.getHoursFormats(), TimeFormat.getHoursFormatNames());
        pd.setPropertyEditor(editor);
        addPropertyChangeListener("hoursFormat", editor);
        descriptors.put(pd);
        
    } catch (IntrospectionException e2) {
        System.out.println(getClass().getName() + " -> " + e2.toString());
        System.exit(0);
    }
    /*
    if (!OVTCore.isServer()) {
        customizer = new TimeSettingsCustomizer(this);
        
        customizer.addPropertyChangeListener("visible", new PropertyChangeListener() {
           public void propertyChange(PropertyChangeEvent evt) {
              firePropertyChange("customizerVisible", null, null);
           } 
        });
    }*/
  
}

protected JFrame getOrbitMonitor() {
  if (orbitMonitor == null) {
    orbitMonitor = new JFrame(getSat().getName());
    orbitMonitor.setIconImage(Toolkit.getDefaultToolkit().getImage(OVTCore.getImagesDir()+"orbitmonitor.gif"));
    orbitMonitor.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
    //orbitMonitor.addWindowListener(new WindowListener() {});
    orbitMonitor.getContentPane().setLayout(new BorderLayout(0,0));
    JPanel monitorPanel = new JPanel();
    setInterior(monitorPanel);
    
    orbitMonitor.getContentPane().add(monitorPanel, BorderLayout.CENTER);
    
    orbitMonitor.pack();
    orbitMonitor.setResizable(false);
  }
  return orbitMonitor;
}

public void setVisible(boolean visible) {
  getOrbitMonitor().setVisible(visible);
  super.setVisible(visible);
  if (isVisible()) refresh();
}

/** Create interior  */
protected void setInterior(Container container) {
        
        GridBagLayout gridbag = new GridBagLayout();
	GridBagConstraints c = new GridBagConstraints();
	c.insets = new Insets(5, 2, 5, 2);
	c.anchor = GridBagConstraints.WEST;
	c.fill = GridBagConstraints.HORIZONTAL;
	container.setLayout(gridbag);

	// Create components

	footprint = new JLabel("Footprint at 100km [SMC]: ");
        for (int i=0; i>2; i++) {
	  latitude[i] = new JTextField("Latitude=50 ");
	  longitude[i] = new JTextField("Longitude=38 ");
        }
	time = new JTextField("2000-01-01 00:00:00");
	//time.setEditable(false);
	
	// Insert

	c.gridx = 0;
	c.gridy = 0;
	c.gridwidth = 1;
	gridbag.setConstraints(time, c);
	container.add(time);
	
	c.gridx = 0;
	c.gridy = 1;
	c.gridwidth = 1;
	JPanel comp = getPositionPanel();
	gridbag.setConstraints(comp, c);
	container.add(comp);
	
	c.gridx = 0;
	c.gridy = 2;
        c.gridwidth = 1;
	comp = getFootprintPanel();
	gridbag.setConstraints(comp, c);
	container.add(comp);
        
        c.gridx = 0;
	c.gridy = 3;
        c.gridwidth = 1;
	comp = getMagnetopauseDistancePanel();
	gridbag.setConstraints(comp, c);
	container.add(comp);
        
        c.gridx = 0;
	c.gridy = 4;
        c.gridwidth = 1;
	comp = getSpinPanel();
	gridbag.setConstraints(comp, c);
	container.add(comp);
        
        c.gridx = 0;
	c.gridy = 5;
        c.gridwidth = 1;
	JPanel panel = new JPanel();
        JButton button = new JButton("Format...");
        button.setToolTipText("Change units, precision, etc.");
        button.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent evt) {
                new OrbitMonitorSettingsWindow(getMyself()).setVisible(true);
            }
        });
        panel.add(button);
        
        button = new JButton("Close");
        button.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent evt) {
                setVisible(false);
            }
        });
        panel.add(button);
        
        showhideDumperButton = new JButton("Dump >>");
        showhideDumperButton.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent evt) {
                setDumperVisible(!isDumperVisible()); // switch ">>" / "<<"
            }
        });
        panel.add(showhideDumperButton);
        
	gridbag.setConstraints(panel, c);
	container.add(panel);
        
}

private OrbitMonitorModule getMyself() {
    return this;
}

protected JPanel getPositionPanel() {

	JPanel container = new JPanel();
	container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
	//container.setBorder(BorderFactory.createEtchedBorder());
	position = new JLabel("Position [GSM]: ");
	x = new JTextField("X=-200.23 RE");
	y = new JTextField("X=-200.23 RE");
	z = new JTextField("X=-200.23 RE");
        radius = new JTextField("Radius=200.23 RE");
	velocity = new JTextField("Velocity=10 Km/s");
        b = new JTextField("B=10.23 nT");

	container.add(position);
	container.add(x);
	container.add(y);
	container.add(z);
	container.add(velocity);
	container.add(radius);
        container.add(b);

	return container;
}


protected JPanel getFootprintPanel() {
	JPanel container = new JPanel();
	container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
	
	// Create components
	
	footprint = new JLabel("Footprint at 100km [SMC], [CGM]");
        container.add(footprint);
        
        for (int i=0; i<2; i++) {
	  latitude[i] = new JTextField("Latitude=50 ");
	  longitude[i] = new JTextField("Longitude=38 ");
          container.add(latitude[i]);
          container.add(longitude[i]);
        }
	return container;
}


protected JPanel getMagnetopauseDistancePanel() {

	JPanel container = new JPanel();
	container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
        
	JLabel title = new JLabel(new String(DumpRecord.strMP_DIST_LABEL));
	dist_to_mpause = new JTextField("r=200.23 RE");
	container.add(title);
	container.add(dist_to_mpause);
	return container;
}

protected JPanel getSpinPanel() { //added by kono

	JPanel container = new JPanel();
	container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
        
	JLabel title = new JLabel(new String(DumpRecord.strSPIN_LABEL));
	spin = new JTextField("B = 20,  V = 31,  S = 12");
	container.add(title);
	container.add(spin);
	return container;
}


public void refresh() {
	refreshPositions();
        refreshSpin();
        //sat.dumper.writeDumpRecord(this.dumpRecord);
        //sat.dumper.close();
}

// is also executed from Sats

public void refreshPositions() {
      int[] records = new int[DumpRecord.numOfFields];
      for (int i=0; i<DumpRecord.numOfFields; i++) records[i] = i;
      String[] values = getValues(records, getMjd());

      time.setText(values[DumpRecord.TIME]);
      String posLabelName="Position ["+CoordinateSystem.getCoordSystem(getCS())+"]";
      position.setText(posLabelName);
      
      x.setText("X=" + values[DumpRecord.POS_X] + getDistanceUnit());
      y.setText("Y=" + values[DumpRecord.POS_Y] + getDistanceUnit());
      z.setText("Z=" + values[DumpRecord.POS_Z] + getDistanceUnit());
      radius.setText("Radius=" + values[DumpRecord.R] + getDistanceUnit());
      velocity.setText("Velocity=" + values[DumpRecord.VEL] + " Km/s");
      b.setText("B=" + values[DumpRecord.B] + " nT");
      
      String fpStrLabel = "Footprint at 100km ["+CoordinateSystem.getCoordSystem(getPolarCS())+"]";
      footprint.setText(fpStrLabel);
      String latUnit = "deg", lonUnit = "deg", latTitle="latitude", lonTitle="longitude";
      if (getPolarCS() == CoordinateSystem.SM) {
          latUnit = "deg"; lonUnit = "h";
          latTitle="lat"; lonTitle="mlt";
      }
      for (int i=0; i<2; i++) {
          if (!values[DumpRecord.FP[i][0]].equals("NaN")) {
                latitude[i].setText(latTitle+"="+values[DumpRecord.FP[i][0]] + " " + latUnit);
                longitude[i].setText(lonTitle+"="+values[DumpRecord.FP[i][1]] + " " + lonUnit);
          } else {
                latitude[i].setText(" none ");
                longitude[i].setText(" none ");
          } 
      }
      dist_to_mpause.setText(values[DumpRecord.DIST_TO_MP] + getDistanceUnit());
}

public void refreshSpin() {
  String[] v = getValues(new int[]{DumpRecord.SPIN_B, DumpRecord.SPIN_V, DumpRecord.SPIN_S }, getMjd());
  if (!v[1].equals("NaN")) spin.setText("B=" + v[0] + ", V=" + v[1] + ", S=" + v[2]);
  else spin.setText(" no data ");
}

public String[] getValues(int[] records, double mjd) {
  
  String[] res = new String[records.length];
  
  TrajectoryPoint trp = getTrajectory().get(mjd);
  if (trp == null) { return null; }
    
  final double NO_FP = Double.MAX_VALUE;  
  double mult = 1.;
  if (getDistanceUnit().equals(km)) mult = Const.RE;
  double[] pos;
  double[][] fp = null;
  double[] spinAngles = null;
  boolean spinAnglesPresent = true;
      
  pos = trp.get(getCS());
    
  for (int n=0; n<records.length; n++) {
    // calculate footprints if they are not already calculated  
    if ((records[n] == DumpRecord.FP1_LAT  ||
        records[n] == DumpRecord.FP2_LAT ||
        records[n] == DumpRecord.FP1_LON  ||
        records[n] == DumpRecord.FP2_LON ) && fp == null) {
            fp = new double[2][2];
            MagPoint[] magPoints = getMagFootprints(mjd);
            MagPoint mp;
            for (int j=0; j<2; j++) {
                mp = magPoints[j];
                if (mp != null) {
                    double[] a = getTrans(getMjd()).gsm_trans_matrix(getPolarCS()).multiply(mp.gsm);
	            if (getPolarCS() == CoordinateSystem.GEO) 
                        fp[j] = Trans.geo2spherical(a); // { deg , deg}
                    else if (getPolarCS() == CoordinateSystem.SM) 
                        fp[j] = Trans.sm2spherical(a); //{"mlat ", "mlt " }
                } else fp[j] = new double[]{NO_FP, NO_FP}; // no fp.
            }
    }
    
    if ((records[n] == DumpRecord.SPIN_B  ||
        records[n] == DumpRecord.SPIN_V  ||
        records[n] == DumpRecord.SPIN_S) && spinAngles == null && spinAnglesPresent) {
            spinAngles = getSat().getSpinAngles();
            if (spinAngles == null) spinAnglesPresent = false;
    }
    
    res[n]="NaN"; // by default
    switch (records[n]) {
        case DumpRecord.TIME : res[n] = timeFormat.format(new Time(mjd)); continue;
        case DumpRecord.POS_X : res[n] = format.format(pos[0]*mult); continue;
        case DumpRecord.POS_Y : res[n] = format.format(pos[1]*mult); continue;
        case DumpRecord.POS_Z : res[n] = format.format(pos[2]*mult); continue;
        case DumpRecord.R  : res[n] = format.format(trp.rr*mult); continue;
        case DumpRecord.VEL  : res[n] = format.format(Vect.absv(trp.vei)); continue;
        case DumpRecord.B    : res[n] = bFormat.format(Vect.absv(getMagProps().bv(trp.gsm, mjd))); continue;
        case DumpRecord.DIST_TO_MP : 
            // distance to mpause
            double dist = Shue97.distance_to_magnetopause(trp.gsm, getMagProps().getSWP(mjd), getMagProps().getIMF(mjd)[2]);
            res[n] = format.format(dist*mult); 
            continue;
        case DumpRecord.FP1_LAT : 
            if (fp[0][0] != NO_FP) res[n] = footprintFormat.format(fp[0][0]);
            continue;
        case DumpRecord.FP1_LON : 
            if (fp[0][1] != NO_FP) res[n] = footprintFormat.format(fp[0][1]);
            continue;
        case DumpRecord.FP2_LAT : 
            if (fp[1][0] != NO_FP) res[n] = footprintFormat.format(fp[1][0]);
            continue;
        case DumpRecord.FP2_LON : 
            if (fp[1][1] != NO_FP) res[n] = footprintFormat.format(fp[1][1]);
            continue;
        case DumpRecord.SPIN_B : 
            if (spinAngles != null) res[n] = spinFormat.format(spinAngles[0]*180./Math.PI);
            continue;    
        case DumpRecord.SPIN_V : 
            if (spinAngles != null) res[n] = spinFormat.format(spinAngles[1]*180./Math.PI);
            continue;    
        case DumpRecord.SPIN_S : 
            if (spinAngles != null) res[n] = spinFormat.format(spinAngles[2]*180./Math.PI);
            continue;    
        
      }
            
    }
    return res;
}

// ----------- events ----------------

public void timeChanged(TimeEvent e) { 
  if (isVisible()) refresh();
}

public void coordinateSystemChanged(CoordinateSystemEvent evt) { 
  if (isVisible()) refresh();
}

public DumpRecord getDumpRecord(){
  return (DumpRecord)this.dumpRecord.clone();
}

/** Getter for property distanceUnit.
 * @return Value of property distanceUnit.
 */
public String getDistanceUnit() {
    return distanceUnit;
}

/** Setter for property distanceUnit.
 * @param distanceUnit New value of property distanceUnit.
 */
public void setDistanceUnit(String distanceUnit) {
    if (!distanceUnit.equals(RE) && !distanceUnit.equals(km))
        throw new IllegalArgumentException("Invalid distance unit : '"+distanceUnit+"'");
    String oldDistanceUnit = this.distanceUnit;
    this.distanceUnit = distanceUnit;
    propertyChangeSupport.firePropertyChange ("distanceUnit", oldDistanceUnit, distanceUnit);
    if (isVisible()) refresh();
}

/** Getter for property distanceFractionDigits.
 * @return Value of property distanceFractionDigits.
 */
public int getDistanceFractionDigits() {
    return format.getMinimumFractionDigits(); // or max, doesn't metter
}

/** Setter for property distanceFractionDigits.
 * @param distanceFractionDigits New value of property distanceFractionDigits.
 */
public void setDistanceFractionDigits(int distanceFractionDigits) {
    if (distanceFractionDigits < 0 || distanceFractionDigits > 4)
        throw new IllegalArgumentException("Precision can be between 0 and 4");
    int oldDistanceFractionDigits = getDistanceFractionDigits();
    format.setMinimumFractionDigits(distanceFractionDigits);
    format.setMaximumFractionDigits(distanceFractionDigits);
    propertyChangeSupport.firePropertyChange ("distanceFractionDigits", new Integer (oldDistanceFractionDigits), new Integer (distanceFractionDigits));
    if (isVisible()) refresh();
}

/** Getter for property distanceFractionDigits.
 * @return Value of property distanceFractionDigits.
 */
public int getFootprintFractionDigits() {
    return format.getMinimumFractionDigits(); // or max, doesn't metter
}

/** Setter for property distanceFractionDigits.
 * @param distanceFractionDigits New value of property distanceFractionDigits.
 */
public void setFootprintFractionDigits(int fractionDigits) {
    if (fractionDigits < 0 || fractionDigits > 4)
        throw new IllegalArgumentException("Precision can be between 0 and 4");
    int oldfractionDigits = getDistanceFractionDigits();
    footprintFormat.setMinimumFractionDigits(fractionDigits);
    footprintFormat.setMaximumFractionDigits(fractionDigits);
    propertyChangeSupport.firePropertyChange ("distanceFractionDigits", new Integer (oldfractionDigits), new Integer (fractionDigits));
    if (isVisible()) refresh();
}

/** Getter for property dumperVisible.
 * @return Value of property dumperVisible.
 */
public boolean isDumperVisible() {
    return dumperVisible;
}

/** Setter for property dumperVisible.
 * @param dumperVisible New value of property dumperVisible.
 */
public void setDumperVisible(boolean dumperVisible) {
    if (this.dumperVisible == dumperVisible) return; // nothing have changed
    boolean oldDumperVisible = this.dumperVisible;
    this.dumperVisible = dumperVisible;
    Container cont = getOrbitMonitor().getContentPane();
    
    if (dumperVisible) {
        JPanel panel = dumper.getPanel();
        cont.add(panel, BorderLayout.SOUTH);
        showhideDumperButton.setText("<< Dumper");
        //panel.setMaximumSize(panel.getSize());
        getOrbitMonitor().pack();
    } else {
        cont.remove(dumper.getPanel());
        showhideDumperButton.setText("Dumper >>");  
        getOrbitMonitor().pack();
    }
    propertyChangeSupport.firePropertyChange ("dumperVisible", new Boolean (oldDumperVisible), new Boolean (dumperVisible));
}

/** Getter for property dateFormat.
 * @return Value of property dateFormat.
 */
public int getDateFormat() {
    return timeFormat.getDateFormat();
}

/** Setter for property dateFormat.
 * @param dateFormat New value of property dateFormat.
 */
public void setDateFormat(int dateFormat) throws IllegalArgumentException {
    int oldDateFormat = getDateFormat();
    timeFormat.setDateFormat(dateFormat);
    propertyChangeSupport.firePropertyChange ("dateFormat", new Integer (oldDateFormat), new Integer (dateFormat));
    if (isVisible()) refresh();
}

/** Getter for property hoursFormat.
 * @return Value of property hoursFormat.
 */
public int getHoursFormat() {
    return timeFormat.getHoursFormat();
}

/** Setter for property hoursFormat.
 * @param hoursFormat New value of property hoursFormat.
 */
public void setHoursFormat(int hoursFormat) throws IllegalArgumentException {
    int oldHoursFormat = getHoursFormat();
    timeFormat.setHoursFormat(hoursFormat);
    propertyChangeSupport.firePropertyChange ("hoursFormat", new Integer (oldHoursFormat), new Integer (hoursFormat));
    if (isVisible()) refresh();
}

}

class OrbitMonitorSettingsWindow extends JDialog {
    
    OrbitMonitorSettingsWindow(OrbitMonitorModule orbitMonitorModule) {
        //super((JDialog)orbitMonitorModule.getOrbitMonitor(), "Orbit Monitor Settings", true);
        super(orbitMonitorModule.getCore().getXYZWin(), "Orbit Monitor Format", true);
        Container cont = getContentPane();
        //create layout : new java.awt.GridLayout (4, 1, 5, 5)
        cont.setLayout(new GridLayout (4, 1, 5, 5));
        
        // -------- Distance panel -------
        Descriptors desc = orbitMonitorModule.getDescriptors();
        JComboBox dateFormatCB = (JComboBox)((ComponentPropertyEditor)(desc.getDescriptor("dateFormat").getPropertyEditor())).getComponent();
        JComboBox hoursFormatCB = (JComboBox)((ComponentPropertyEditor)(desc.getDescriptor("hoursFormat").getPropertyEditor())).getComponent();
        JComboBox distUnitsCB = (JComboBox)((ComponentPropertyEditor)(desc.getDescriptor("distanceUnit").getPropertyEditor())).getComponent();
        JComboBox distFractionDigitsCB = (JComboBox)((ComponentPropertyEditor)(desc.getDescriptor("distanceFractionDigits").getPropertyEditor())).getComponent();
        JComboBox footprintFractionDigitsCB = (JComboBox)((ComponentPropertyEditor)(desc.getDescriptor("footprintFractionDigits").getPropertyEditor())).getComponent();
        
        JPanel panel = new JPanel();
            panel.setBorder(new TitledBorder("Time"));
            panel.add(dateFormatCB);
            panel.add(hoursFormatCB);
        cont.add(panel);
        
        panel = new JPanel();
            panel.setBorder(new TitledBorder("Distance"));
            panel.add(new JLabel("in : "));
            panel.add(distUnitsCB);
            panel.add(new JLabel(" precision : "));
            panel.add(distFractionDigitsCB);
        cont.add(panel);
        
        panel = new JPanel();
            panel.setBorder(new TitledBorder("Footprints"));
            panel.add(new JLabel(" precision : "));
            panel.add(footprintFractionDigitsCB);
        cont.add(panel);
        
        // ------------------- ok button ----------------
        
        JButton okButton = new JButton("OK");
            okButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent evt) {
                    dispose();
                }
            });
            okButton.setMargin(new Insets(10, 40, 10, 40));
            okButton.setVerticalAlignment(SwingConstants.CENTER);
            panel = new JPanel();
            panel.add(okButton);
        cont.add(panel);
        
        pack();
        //setResizable(false);
        
        // senter the window
        Dimension scrnSize = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension windowSize = getSize();
        setLocation(scrnSize.width/2 - windowSize.width/2,
                 scrnSize.height/2 - windowSize.height/2);
    }
    
}



