// Path: src/org/opensourcephysics/cabrillo/tracker/CircleFitterStep.java
// class DataPoint extends TPoint {
//   	
//   /**
//    * Constructs a DataPoint with specified image coordinates.
//    *
//    * @param x the x coordinate
//    * @param y the y coordinate
//    */
//   public DataPoint(double x, double y) {
//     super(x, y);
//     setStepEditTrigger(true);
//   }
// 
//   /**
//    * Overrides TPoint setXY method.
//    *
//    * @param x the x coordinate
//    * @param y the y coordinate
//    */
//   public void setXY(double x, double y) {
//     if (getTrack().locked) return;
// 
//     if (circleFitter.isFixed()) {
//     	int row = 0;
//   		for (int j=0; j<dataPoints[0].length; j++) {
//     		if (this==dataPoints[0][j]) {
//     			row = j;
//     			break;
//     		}
//     	}
//     	CircleFitterStep keyStep = (CircleFitterStep)circleFitter.steps.getStep(0);
//     	while (keyStep.dataPoints[0].length<=row) {
//     		keyStep.addDataPoint(keyStep.new DataPoint(0, 0), false);
//     	}
//     	keyStep.dataPoints[0][row].setLocation(x, y); // set property of step 0
//     	if (doRefresh) keyStep.refreshCircle();
//     	if (doRefresh) circleFitter.refreshStep(CircleFitterStep.this); // sets properties of this step
//     }
//     else {
//     	setLocation(x, y);
//     	if (!this.isAttached())
//     		circleFitter.keyFrames.add(n);
//     	if (doRefresh) refreshCircle();
//   	}
//     if (doRefresh) circleFitter.refreshFields(n);
//       
//  	circleFitter.dataValid = false;
//  	if (doRefresh) circleFitter.firePropertyChange("data", null, circleFitter); //$NON-NLS-1$
//     if (circleFitter.trackerPanel != null) {
//     	circleFitter.trackerPanel.changed = true;
//     }
//   }
// 
//   @Override
//   public void setScreenPosition(int x, int y, VideoPanel vidPanel, InputEvent e) {
//   	if (this.isAttached()) return; // don't drag or nudge when attached to another point
//     setScreenPosition(x, y, vidPanel);
//   }
// 
//   @Override
//   public String toString() {
//   	return "DataPoint "+n+": "+super.toString(); //$NON-NLS-1$ //$NON-NLS-2$
//   }
//     
//   public Step getAttachedStep() {
//   	TTrack track = getTrack();
//   	if (this.attachedTo!=null && track.trackerPanel!=null) {
//   		ArrayList<PointMass> masses = track.trackerPanel.getDrawables(PointMass.class);
//   		for (PointMass next: masses) {
//   			Step step = next.getStep(attachedTo, track.trackerPanel);
//   			if (step!=null) return step;
//   		}
//   	}
//   	return null;
//   }
// 
// }
// 
// Path: src/org/opensourcephysics/cabrillo/tracker/CircleFitterStep.java
// class CenterPoint extends TPoint {
//   	
//   /**
//    * Constructs a CenterPoint with specified image coordinates.
//    *
//    * @param x the x coordinate
//    * @param y the y coordinate
//    */
//   public CenterPoint(double x, double y) {
//     super(x, y);
//   }
// 
//   /**
//    * Overrides TPoint setXY method to prevent user dragging/nudging.
//    *
//    * @param x the x coordinate
//    * @param y the y coordinate
//    */
//   public void setXY(double x, double y) {
//     return;
//   }
// 
// }


import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeSet;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.*;
import java.awt.geom.Point2D;
import java.beans.PropertyChangeEvent;
import javax.swing.*;
import javax.swing.border.Border;
import org.opensourcephysics.display.*;
import org.opensourcephysics.media.core.*;
import org.opensourcephysics.tools.FontSizer;
import org.opensourcephysics.cabrillo.tracker.CircleFitterStep.DataPoint;
import org.opensourcephysics.cabrillo.tracker.CircleFitterStep.CenterPoint;
import org.opensourcephysics.controls.*;
    CircleFitterStep step = new CircleFitterStep(this, 0);
    step.setFootprint(getFootprint());
    steps = new StepArray(step); // autofills
  	keyFrames.add(0);
    fixedItem = new JCheckBoxMenuItem(TrackerRes.getString("TapeMeasure.MenuItem.Fixed")); //$NON-NLS-1$
    fixedItem.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent e) {
        setFixed(fixedItem.isSelected());
      }
    });
    
    // create attachment dialog item
  	attachmentItem = new JMenuItem(TrackerRes.getString("MeasuringTool.MenuItem.Attach")); //$NON-NLS-1$
  	attachmentItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
      	AttachmentDialog control = trackerPanel.getAttachmentDialog(CircleFitter.this);
      	control.setVisible(true);
      }
    });

  	clickToMarkLabel = new JLabel();
    clickToMarkLabel.setForeground(Color.red.darker());
    
    // create actions, listeners, labels and fields for data points
    final Action dataPointAction = new AbstractAction() {
      public void actionPerformed(ActionEvent e) {
      	if (trackerPanel==null) return;
      	if (e!=null && e.getSource()==xDataField && xDataField.getBackground()!=Color.yellow) return;
      	if (e!=null && e.getSource()==yDataField && yDataField.getBackground()!=Color.yellow) return;
        TPoint p = trackerPanel.getSelectedPoint();
// Path: src/org/opensourcephysics/cabrillo/tracker/CircleFitterStep.java
// class DataPoint extends TPoint {
//   	
//   /**
//    * Constructs a DataPoint with specified image coordinates.
//    *
//    * @param x the x coordinate
//    * @param y the y coordinate
//    */
//   public DataPoint(double x, double y) {
//     super(x, y);
//     setStepEditTrigger(true);
//   }
// 
//   /**
//    * Overrides TPoint setXY method.
//    *
//    * @param x the x coordinate
//    * @param y the y coordinate
//    */
//   public void setXY(double x, double y) {
//     if (getTrack().locked) return;
// 
//     if (circleFitter.isFixed()) {
//     	int row = 0;
//   		for (int j=0; j<dataPoints[0].length; j++) {
//     		if (this==dataPoints[0][j]) {
//     			row = j;
//     			break;
//     		}
//     	}
//     	CircleFitterStep keyStep = (CircleFitterStep)circleFitter.steps.getStep(0);
//     	while (keyStep.dataPoints[0].length<=row) {
//     		keyStep.addDataPoint(keyStep.new DataPoint(0, 0), false);
//     	}
//     	keyStep.dataPoints[0][row].setLocation(x, y); // set property of step 0
//     	if (doRefresh) keyStep.refreshCircle();
//     	if (doRefresh) circleFitter.refreshStep(CircleFitterStep.this); // sets properties of this step
//     }
//     else {
//     	setLocation(x, y);
//     	if (!this.isAttached())
//     		circleFitter.keyFrames.add(n);
//     	if (doRefresh) refreshCircle();
//   	}
//     if (doRefresh) circleFitter.refreshFields(n);
//       
//  	circleFitter.dataValid = false;
//  	if (doRefresh) circleFitter.firePropertyChange("data", null, circleFitter); //$NON-NLS-1$
//     if (circleFitter.trackerPanel != null) {
//     	circleFitter.trackerPanel.changed = true;
//     }
//   }
// 
//   @Override
//   public void setScreenPosition(int x, int y, VideoPanel vidPanel, InputEvent e) {
//   	if (this.isAttached()) return; // don't drag or nudge when attached to another point
//     setScreenPosition(x, y, vidPanel);
//   }
// 
//   @Override
//   public String toString() {
//   	return "DataPoint "+n+": "+super.toString(); //$NON-NLS-1$ //$NON-NLS-2$
//   }
//     
//   public Step getAttachedStep() {
//   	TTrack track = getTrack();
//   	if (this.attachedTo!=null && track.trackerPanel!=null) {
//   		ArrayList<PointMass> masses = track.trackerPanel.getDrawables(PointMass.class);
//   		for (PointMass next: masses) {
//   			Step step = next.getStep(attachedTo, track.trackerPanel);
//   			if (step!=null) return step;
//   		}
//   	}
//   	return null;
//   }
// 
// }
// 
// Path: src/org/opensourcephysics/cabrillo/tracker/CircleFitterStep.java
// class CenterPoint extends TPoint {
//   	
//   /**
//    * Constructs a CenterPoint with specified image coordinates.
//    *
//    * @param x the x coordinate
//    * @param y the y coordinate
//    */
//   public CenterPoint(double x, double y) {
//     super(x, y);
//   }
// 
//   /**
//    * Overrides TPoint setXY method to prevent user dragging/nudging.
//    *
//    * @param x the x coordinate
//    * @param y the y coordinate
//    */
//   public void setXY(double x, double y) {
//     return;
//   }
// 
// }


// Path: src/org/opensourcephysics/cabrillo/tracker/CircleFitter.java
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeSet;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.*;
import java.awt.geom.Point2D;
import java.beans.PropertyChangeEvent;
import javax.swing.*;
import javax.swing.border.Border;
import org.opensourcephysics.display.*;
import org.opensourcephysics.media.core.*;
import org.opensourcephysics.tools.FontSizer;
import org.opensourcephysics.cabrillo.tracker.CircleFitterStep.DataPoint;
import org.opensourcephysics.cabrillo.tracker.CircleFitterStep.CenterPoint;
import org.opensourcephysics.controls.*;

    CircleFitterStep step = new CircleFitterStep(this, 0);
    step.setFootprint(getFootprint());
    steps = new StepArray(step); // autofills
  	keyFrames.add(0);
    fixedItem = new JCheckBoxMenuItem(TrackerRes.getString("TapeMeasure.MenuItem.Fixed")); //$NON-NLS-1$
    fixedItem.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent e) {
        setFixed(fixedItem.isSelected());
      }
    });
    
    // create attachment dialog item
  	attachmentItem = new JMenuItem(TrackerRes.getString("MeasuringTool.MenuItem.Attach")); //$NON-NLS-1$
  	attachmentItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
      	AttachmentDialog control = trackerPanel.getAttachmentDialog(CircleFitter.this);
      	control.setVisible(true);
      }
    });

  	clickToMarkLabel = new JLabel();
    clickToMarkLabel.setForeground(Color.red.darker());
    
    // create actions, listeners, labels and fields for data points
    final Action dataPointAction = new AbstractAction() {
      public void actionPerformed(ActionEvent e) {
      	if (trackerPanel==null) return;
      	if (e!=null && e.getSource()==xDataField && xDataField.getBackground()!=Color.yellow) return;
      	if (e!=null && e.getSource()==yDataField && yDataField.getBackground()!=Color.yellow) return;
        TPoint p = trackerPanel.getSelectedPoint();
        if (!(p instanceof DataPoint)) return;