00001 package edu.stanford.hci.r3.tools.design.sketch;
00002
00003 import java.awt.geom.Point2D;
00004 import java.awt.geom.Rectangle2D;
00005 import java.io.File;
00006 import java.io.FileNotFoundException;
00007 import java.io.FileOutputStream;
00008 import java.io.IOException;
00009 import java.io.PrintStream;
00010 import java.text.DecimalFormat;
00011 import java.util.ArrayList;
00012 import java.util.List;
00013 import java.util.regex.Matcher;
00014 import java.util.regex.Pattern;
00015
00016 import edu.stanford.hci.r3.PaperToolkit;
00017 import edu.stanford.hci.r3.pen.Pen;
00018 import edu.stanford.hci.r3.pen.PenSample;
00019 import edu.stanford.hci.r3.pen.batch.PenSynch;
00020 import edu.stanford.hci.r3.pen.handwriting.HandwritingRecognitionService;
00021 import edu.stanford.hci.r3.pen.ink.Ink;
00022 import edu.stanford.hci.r3.pen.ink.InkStroke;
00023 import edu.stanford.hci.r3.pen.ink.InkUtils;
00024 import edu.stanford.hci.r3.pen.streaming.listeners.PenListener;
00025 import edu.stanford.hci.r3.tools.design.util.Regions;
00026 import edu.stanford.hci.r3.util.DebugUtils;
00027 import edu.stanford.hci.r3.util.files.FileUtils;
00028
00040 public class SketchToPaperUI {
00041
00045 private static void testTranslateXMLFile() {
00046 String fileName =
00047 "penSynch/data/XML/2007_03_10__01_09_38_SketchedPaperUI.xml";
00048 new SketchToPaperUI().translate(new File(fileName), "SketchedPaperUI", new File("."));
00049 }
00050
00051 private Pen pen;
00052
00056 public SketchToPaperUI() {
00057 DebugUtils.println("New Sketch To Paper UI");
00058
00059
00060 pen = new Pen();
00061 pen.startLiveMode();
00062 pen.addLivePenListener(new PenListener() {
00063 @Override
00064 public void penDown(PenSample sample) {
00065
00066 }
00067
00068 @Override
00069 public void penUp(PenSample sample) {
00070
00071 }
00072
00073 @Override
00074 public void sample(PenSample sample) {
00075
00076 }
00077 });
00078 }
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00097 public void addPenListener(PenListener penListener) {
00098 pen.addLivePenListener(penListener);
00099 }
00100
00104 public void exit() {
00105 DebugUtils.println("Exiting Sketch To Paper UI");
00106 pen.stopLiveMode();
00107 }
00108
00115 public void translate(File strokeFile, String className, File outputFolder) {
00116 PenSynch penSynch = new PenSynch(strokeFile);
00117 List<Ink> importedInk = penSynch.getImportedInk();
00118
00119
00120
00121
00122
00123 InkStroke biggestStroke = InkUtils.getStrokeWithLargestArea(importedInk);
00124
00125
00126 List<InkStroke> regionStrokes = InkUtils.getAllStrokesContainedWithin(importedInk, biggestStroke);
00127
00128
00129 List<InkStroke> connectors = InkUtils.getStrokesPartlyOutside(importedInk, biggestStroke);
00130
00131
00132 List<InkStroke> outsideStrokes = InkUtils.getAllStrokesOutside(importedInk, biggestStroke);
00133
00134 List<Ink> events = InkUtils.clusterStrokes(outsideStrokes, 2);
00135
00136
00137 HandwritingRecognitionService service = HandwritingRecognitionService.getInstance();
00138
00139
00140 Rectangle2D sheet = biggestStroke.getBounds();
00141 double scale = Regions.makeItFit(sheet.getWidth(), sheet.getHeight(), 8.5, 11);
00142
00143
00144 PrintStream outXML = null;
00145 PrintStream outJava = null;
00146 try {
00147 outXML = new PrintStream(new FileOutputStream(new File(outputFolder, className + ".xml")));
00148 outJava = new PrintStream(new FileOutputStream(new File(outputFolder, className + ".java")));
00149 } catch (FileNotFoundException e1) {
00150 e1.printStackTrace();
00151 }
00152
00153
00154 DecimalFormat df = new DecimalFormat("0.###");
00155
00156 outXML.println("<sheet width=\"" + df.format(sheet.getWidth() * scale) + "\" height=\""
00157 + df.format(sheet.getHeight() * scale) + "\">");
00158
00159 class Region {
00160
00161 Rectangle2D bounds = null;
00162 String eventType = null;
00163 String name = null;
00164 }
00165
00166 List<Region> regions = new ArrayList<Region>();
00167
00168
00169 int strokeId = 1;
00170 for (InkStroke region : regionStrokes) {
00171 Region r = new Region();
00172 regions.add(r);
00173
00174 r.bounds = region.getBounds();
00175 InkStroke c = null;
00176
00177 for (InkStroke connection : connectors) {
00178 if (connection.getBounds().intersects(r.bounds)) {
00179 c = connection;
00180 break;
00181 }
00182 }
00183 Ink event = null;
00184
00185 if (c != null) {
00186
00187
00188 PenSample p = c.getStart();
00189 if (r.bounds.contains(p.getX(), p.getY()))
00190 p = c.getEnd();
00191
00192
00193 event = InkUtils.getInkNearPoint(events, new Point2D.Double(p.getX(), p.getY()), 40.0);
00194
00195
00196 if (event != null) {
00197
00198 String result = service.recognizeHandwriting(event
00199 .getAsXML(false ));
00200
00201
00202 String pieces[] = result.split("[^a-zA-Z0-9]");
00203
00204 if (pieces.length > 1)
00205 r.name = pieces[1];
00206
00207 r.eventType = pieces[0].toLowerCase();
00208
00209 }
00210 }
00211
00212
00213
00214 if (r.name == null)
00215 r.name = "region" + (strokeId++);
00216
00217 r.name = Character.toUpperCase(r.name.charAt(0)) + r.name.substring(1);
00218
00219
00220 outXML.print(" <region name=\"" + r.name + "\" x=\""
00221 + df.format((r.bounds.getX() - sheet.getX()) * scale) + "\" y=\""
00222 + df.format((r.bounds.getY() - sheet.getY()) * scale) + "\" width=\""
00223 + df.format(r.bounds.getWidth() * scale) + "\" height=\""
00224 + df.format(r.bounds.getHeight() * scale) + "\"");
00225 if (event != null) {
00226 outXML.println(">");
00227 outXML.println(" <eventHandler type=\"" + r.eventType + "\"/>");
00228 outXML.println(" </region>");
00229 } else {
00230 outXML.println("/>");
00231 }
00232 }
00233 outXML.println("</sheet>");
00234 outXML.close();
00235
00236
00237 String template = FileUtils.readFileIntoStringBuffer(
00238 PaperToolkit.getResourceFile("/designer/template.txt")).toString();
00239
00240 template = template.replace("{CLASSNAME}", className);
00241
00242
00243
00244 Matcher repeatMatcher = Pattern.compile("\\{REPEAT:REGIONS\\}([\\s\\S]*?)\\{/REPEAT:REGIONS\\}",
00245 Pattern.MULTILINE | Pattern.CASE_INSENSITIVE).matcher(template);
00246 System.out.println("Matches = " + repeatMatcher.matches());
00247
00248 int lastPosition = 0;
00249
00250 while (repeatMatcher.find()) {
00251
00252 outJava.print(template.substring(lastPosition, repeatMatcher.start()));
00253
00254
00255 for (Region region : regions) {
00256
00257 String repeatString = repeatMatcher.group(1).replace("{REGION.NAME}", region.name);
00258
00259
00260
00261 Matcher ifMatcher = Pattern.compile("\\{IF:([A-Z]+)\\}([\\s\\S]*?)\\{/IF:([A-Z]+)\\}",
00262 Pattern.MULTILINE | Pattern.CASE_INSENSITIVE).matcher(repeatString);
00263
00264 int lastPosition2 = 0;
00265
00266 while (ifMatcher.find()) {
00267
00268 outJava.print(repeatString.substring(lastPosition2, ifMatcher.start()));
00269
00270 String type = ifMatcher.group(1);
00271 String ifString = ifMatcher.group(2);
00272
00273
00274
00275 if (type.toLowerCase().equals(region.eventType))
00276 outJava.print(ifString);
00277 lastPosition2 = ifMatcher.end();
00278 }
00279
00280 outJava.print(repeatString.substring(lastPosition2));
00281 }
00282 lastPosition = repeatMatcher.end();
00283 }
00284
00285 outJava.print(template.substring(lastPosition));
00286
00287 outJava.close();
00288
00289
00290 service.exitServer();
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 }
00320 }