00001 package edu.stanford.hci.r3.pattern.calibrate;
00002
00003 import java.awt.Component;
00004 import java.awt.event.ActionEvent;
00005 import java.awt.event.ActionListener;
00006 import java.io.File;
00007
00008 import javax.swing.BorderFactory;
00009 import javax.swing.Box;
00010 import javax.swing.BoxLayout;
00011 import javax.swing.JButton;
00012 import javax.swing.JFrame;
00013 import javax.swing.JLabel;
00014 import javax.swing.JPanel;
00015
00016 import edu.stanford.hci.r3.Application;
00017 import edu.stanford.hci.r3.PaperToolkit;
00018 import edu.stanford.hci.r3.pen.Pen;
00019 import edu.stanford.hci.r3.pen.batch.BatchedEventHandler;
00020 import edu.stanford.hci.r3.pen.ink.Ink;
00021 import edu.stanford.hci.r3.pen.ink.InkStroke;
00022 import edu.stanford.hci.r3.pen.streaming.listeners.PenListener;
00023 import edu.stanford.hci.r3.pen.streaming.listeners.PenStrokeListener;
00024 import edu.stanford.hci.r3.util.DebugUtils;
00025 import edu.stanford.hci.r3.util.MathUtils;
00026 import edu.stanford.hci.r3.util.WindowUtils;
00027 import edu.stanford.hci.r3.util.files.FileUtils;
00028
00061 public class CalibrationCaptureApp {
00062
00066 public static void main(String[] args) {
00067 new CalibrationCaptureApp();
00068 }
00069
00070 private Application app;
00071
00072 private BatchedEventHandler beh;
00073
00074 private CalibrationEngine calibrate = new CalibrationEngine();
00075
00076 private JButton calibrateButton;
00077
00078 private Ink currStreamedInk;
00079
00080 private JFrame frame;
00081
00082 private PenListener listener;
00083
00084 private JPanel mainPanel;
00085
00086 private Pen pen;
00087
00088 private Ink savedBatchedInk;
00089
00090 private Ink savedStreamedInk;
00091
00092 private JButton saveStrokesButton;
00093
00094 private long streamedStrokesFileName;
00095
00096 private JLabel streamedStrokesInfoLabel;
00097
00098 private PaperToolkit toolkit;
00099
00103 public CalibrationCaptureApp() {
00104 PaperToolkit.initializeLookAndFeel();
00105 setupGUI();
00106
00107 app = new Application("Calibration");
00108 app.addPenInput(getPen());
00109 app.addBatchEventHandler(getBatchedEventHandler());
00110 toolkit = new PaperToolkit(true, false, false);
00111 toolkit.startApplication(app);
00112 }
00113
00117 private void alignStreamedAndBatchedStrokes() {
00118 calibrate.alignInkStrokes(savedStreamedInk, savedBatchedInk);
00119 }
00120
00124 private BatchedEventHandler getBatchedEventHandler() {
00125 if (beh == null) {
00126 beh = new BatchedEventHandler("Calibration") {
00127 @Override
00128 public void inkArrived(Ink inkOnThisPage) {
00129 saveBatchedStrokes(inkOnThisPage);
00130 }
00131
00132 };
00133 }
00134 return beh;
00135 }
00136
00140 private Component getCalibrateButton() {
00141 if (calibrateButton == null) {
00142 calibrateButton = new JButton("Calibrate (Align Streamed & Batched Strokes)");
00143 calibrateButton.setAlignmentX(Component.CENTER_ALIGNMENT);
00144 calibrateButton.addActionListener(new ActionListener() {
00145 public void actionPerformed(ActionEvent e) {
00146 alignStreamedAndBatchedStrokes();
00147 }
00148 });
00149 }
00150 return calibrateButton;
00151 }
00152
00156 private Component getPanel() {
00157 if (mainPanel == null) {
00158 mainPanel = new JPanel();
00159 mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
00160 mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));
00161 mainPanel.add(getSaveStreamedStrokesButton());
00162 mainPanel.add(Box.createVerticalStrut(10));
00163 mainPanel.add(getStreamedStrokesInfoLabel());
00164 mainPanel.add(Box.createVerticalStrut(10));
00165 mainPanel.add(getCalibrateButton());
00166 }
00167 return mainPanel;
00168 }
00169
00173 private Pen getPen() {
00174 if (pen == null) {
00175 pen = new Pen();
00176 pen.addLivePenListener(getPenListener());
00177 }
00178 return pen;
00179 }
00180
00184 private PenListener getPenListener() {
00185 if (listener == null) {
00186 listener = new PenStrokeListener() {
00187 @Override
00188 public void penStroke(InkStroke stroke) {
00189 if (currStreamedInk == null) {
00190 currStreamedInk = new Ink();
00191 }
00192
00193 currStreamedInk.addStroke(stroke);
00194 DebugUtils.println(currStreamedInk.getNumStrokes() + " strokes collected.");
00195
00196 final double[] samplesX = stroke.getXSamples();
00197 final double[] samplesY = stroke.getYSamples();
00198 DebugUtils.println("STDEV X: " + MathUtils.standardDeviation(samplesX));
00199 DebugUtils.println("STDEV Y: " + MathUtils.standardDeviation(samplesY));
00200 }
00201 };
00202 }
00203 return listener;
00204 }
00205
00209 private Component getSaveStreamedStrokesButton() {
00210 if (saveStrokesButton == null) {
00211 saveStrokesButton = new JButton("Save Streamed Strokes");
00212 saveStrokesButton.setAlignmentX(Component.CENTER_ALIGNMENT);
00213 saveStrokesButton.addActionListener(new ActionListener() {
00214 public void actionPerformed(ActionEvent arg0) {
00215 saveStreamedStrokes();
00216 }
00217
00218 });
00219 }
00220 return saveStrokesButton;
00221 }
00222
00226 private Component getStreamedStrokesInfoLabel() {
00227 if (streamedStrokesInfoLabel == null) {
00228 streamedStrokesInfoLabel = new JLabel("No Saved Strokes");
00229 streamedStrokesInfoLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
00230 }
00231 return streamedStrokesInfoLabel;
00232 }
00233
00239 private void saveBatchedStrokes(Ink inkOnThisPage) {
00240 savedBatchedInk = inkOnThisPage;
00241 FileUtils.writeStringToFile(inkOnThisPage.getAsXML(), new File("data/calibration/"
00242 + streamedStrokesFileName + ".batched.xml"));
00243 }
00244
00248 private void saveStreamedStrokes() {
00249 savedStreamedInk = currStreamedInk;
00250 currStreamedInk = null;
00251 streamedStrokesFileName = System.currentTimeMillis();
00252 FileUtils.writeStringToFile(savedStreamedInk.getAsXML(), new File("data/calibration/"
00253 + streamedStrokesFileName + ".streamed.xml"));
00254 streamedStrokesInfoLabel.setText(savedStreamedInk.getNumStrokes() + " strokes saved.");
00255 }
00256
00260 private void setupGUI() {
00261 frame = new JFrame("Pen Calibration");
00262 frame.add(getPanel());
00263 frame.pack();
00264 frame.setLocation(WindowUtils.getWindowOrigin(frame, WindowUtils.DESKTOP_CENTER));
00265 frame.setVisible(true);
00266 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
00267 }
00268 }