package com.drawbridge.utils; import java.awt.Color; import java.awt.Dimension; import java.awt.Point; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.SwingUtilities; import com.drawbridge.dm.DMImageFactory.DMImage; import com.drawbridge.dm.DMSimplePanel; import com.drawbridge.jsengine.JsEngine; import com.drawbridge.text.TextPanel; import com.google.caja.lexer.FilePosition; import com.google.caja.lexer.InputSource; public class JSUtils { private static int nameIndex = 0; /** * Generates valid JavaScript code to display a given set of DMImages * @param ArrayList of DMImages Assignment ps: * @return JavaScript code */ public static String generateDMImageJS(List<DMImage> images){ String result = "// Draw the images on the canvas\n"; for(int i = 0; i < images.size(); i++){ String objectName = images.get(i).getName(); Point loc = images.get(i).getPreferredLocation(); Dimension size = images.get(i).getPreferredSize(); result += "var " + objectName + " = loadImage(" + i + ", " + (int) loc.getX() + ", " + (int) loc.getY() + ", " + (int) (size.getWidth() - ( 2 * images.get(i).getHandleThickness())) + ", " + (int) (size.getHeight() - ( 2 * images.get(i).getHandleThickness())) + ");"; result += (i != images.size() -1) ? "\n" : ""; } return result; } /** * Generates valid JavaScript code to display the canvas * @param ArrayList of DMImages * @return JavaScript code */ public static String generateCanvasJS(){ return "// Get the canvas so we can draw something\n" + "var canvas = document.getElementById(\"myCanvas\");\n\n" + "// Paint Background\n" + "var myColour = Colour.getRGB(255, 255, 255);\n" + "canvas.setBackgroundColour(myColour);\n"; } public static String generateImageName(){ return "image" + nameIndex++; } public static final String JS_CANVAS_RESET = ("clear();"); private static HashSet<String> keywords = new HashSet<String>(){ private static final long serialVersionUID = 1019297538895274071L; { add("in"); add("if"); add("for"); add("while"); add("finally"); add("var"); add("new"); add("function"); add("do"); add("return"); add("void"); add("else"); add("break"); add("catch"); add("instanceof"); add("with"); add("throw"); add("case"); add("default"); add("try"); add("this"); add("switch"); add("continue"); add("typeof"); add("delete"); add("let"); add("yield"); add("const"); add("true"); add("false"); add("null"); add("undefined"); add("NaN"); add("Infinity"); } ; }; public static ArrayList<HighlightElement> getHighlightElements(String javascript){ ArrayList<HighlightElement> results = new ArrayList<HighlightElement>(); ArrayList<HighlightElement> tokens = getMatchingKeywords(javascript); ArrayList<HighlightElement> stringLiterals = getStringLiterals(javascript); ArrayList<HighlightElement> literals = getLiterals(javascript); ArrayList<HighlightElement> comments = getComments(javascript); ArrayList<HighlightElement> functionCalls = getFunctionCalls(javascript); results.addAll(literals); results.addAll(tokens); results.addAll(stringLiterals); results.addAll(comments); results.addAll(functionCalls); return results; } public static ArrayList<HighlightElement> getMatchingKeywords(String string){ ArrayList<HighlightElement> tokens = new ArrayList<HighlightElement>(); String stringPattern = "(^|[\\s])[A-Za-z]+"; Pattern pattern = Pattern.compile(stringPattern); Matcher matcher = pattern.matcher(string); while (matcher.find()) { String result = matcher.group().replaceAll("[\\s]", ""); result = result.replaceAll("\\n", ""); if(keywords.contains(result)){ tokens.add(new HighlightElement(Color.decode("#BF2DA6"), matcher.start(), matcher.end()-1)); } } return tokens; } public static ArrayList<HighlightElement> getStringLiterals(String string){ ArrayList<HighlightElement> tokens = new ArrayList<HighlightElement>(); String stringPattern = "[\'][\']*[\']"; Pattern pattern = Pattern.compile(stringPattern); Matcher matcher = pattern.matcher(string); while (matcher.find()) { tokens.add(new HighlightElement(Color.decode("#D12B24"), matcher.start(), matcher.end()-1)); } stringPattern = "[\"][^\"]*[\"]"; pattern = Pattern.compile(stringPattern); matcher = pattern.matcher(string); while (matcher.find()) { tokens.add(new HighlightElement(Color.decode("#D12B24"), matcher.start(), matcher.end()-1)); } return tokens; } public static ArrayList<HighlightElement> getComments(String string) { ArrayList<HighlightElement> tokens = new ArrayList<HighlightElement>(); String stringPattern = "[\\/][\\/].*"; Pattern pattern = Pattern.compile(stringPattern); Matcher matcher = pattern.matcher(string); while (matcher.find()) { tokens.add(new HighlightElement(Color.decode("#008425"), matcher.start(), matcher.end()-1)); } return tokens; } public static ArrayList<HighlightElement> getFunctionCalls(String string) { ArrayList<HighlightElement> tokens = new ArrayList<HighlightElement>(); String stringPattern = "[A-Za-z]+[(]"; Pattern pattern = Pattern.compile(stringPattern); Matcher matcher = pattern.matcher(string); while (matcher.find()) { tokens.add(new HighlightElement(Color.decode("#42B5E7"), matcher.start(), matcher.end()-2)); } return tokens; } public static ArrayList<HighlightElement> getLiterals(String string) { ArrayList<HighlightElement> tokens = new ArrayList<HighlightElement>(); String stringPattern = "[\\(\\=\\,\\+\\-\\\\\\s][0-9]+[.]?[0-9]*"; Pattern pattern = Pattern.compile(stringPattern); Matcher matcher = pattern.matcher(string); while (matcher.find()) { String startChar = string.substring(matcher.start(), matcher.start()+1); String allowedStartChars = "( +-=,"; int start = matcher.start(); int end = matcher.end() - 1; if(allowedStartChars.contains(startChar)) start++; tokens.add(new HighlightElement(Color.decode("#049999"), start, end)); } return tokens; } public static FilePosition getNewFilePosition(FilePosition oldFilePos, int newLength){ if(oldFilePos.length() < newLength){ return oldFilePos.narrowTo(0, newLength); } else{ int linePos = oldFilePos.startLineNo(); int oldStartCharInFile = oldFilePos.startCharInFile(); int xPos = TextPanel.getInstance().getDocument().getDocumentModel().getCharPositionFromStringIndex(oldStartCharInFile-1).x; FilePosition newFilePos = FilePosition.instance(InputSource.UNKNOWN, linePos, oldStartCharInFile, xPos, newLength); return newFilePos; } } public static void printFilePosition(FilePosition filePosition) { Utils.out.println(JSUtils.class,"FilePosition: " + filePosition.startCharInFile() + ", " + filePosition.endCharInFile()); } public static void executeStaticImageCode(LinkedList<DMImage> dmImages, final boolean requestAnimation) { // Follow on the update sequence with Code Generation String code = JSUtils.generateCanvasJS() + "\n"; code += JSUtils.generateDMImageJS(dmImages); final String resultCode = code; SwingUtilities.invokeLater(new Runnable(){ @Override public void run() { if(TextPanel.hasInstance()) TextPanel.getInstance().setText(JSUtils.class, resultCode); JsEngine.getInstance().executeCode(null, resultCode, false); //<- this used to be important //Execute if(requestAnimation){ Utils.out.println(this.getClass(),"Executing from DMModel"); DMSimplePanel.getInstance().requestAnimationStart(); } } }); } public static void resetImageNameCounter() { nameIndex = 0; } }