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 }