private void renderTreeHelper(XML xml, int[] widths, int depth, int[] ltor) { float x = (g.width / widths[depth]) * (0.5f + ltor[depth]++); float y = (g.height / widths.length) * (0.5f + depth); xml.setFloat("x", x); xml.setFloat("y", y); if (xml.getParent() != null) g.line( xml.getParent().getFloat("x"), xml.getParent().getFloat("y") + RECT_HEIGHT / 2, x, y - RECT_HEIGHT / 2); if (xml.hasAttribute("altColor")) { String hexColor = xml.getString("altColor"); g.fill( getColorComponent(hexColor, 0), getColorComponent(hexColor, 1), getColorComponent(hexColor, 2)); } g.rect(x, y, RECT_WIDTH, RECT_HEIGHT, 4); g.fill(0); if (xml.hasAttribute("altName")) g.text(xml.getString("altName"), x, y, RECT_WIDTH, RECT_HEIGHT); else g.text(xml.getName(), x, y, RECT_WIDTH, RECT_HEIGHT); g.fill(255); XML[] children = xml.getChildren(); for (int i = 0; i < children.length; i++) renderTreeHelper(children[i], widths, depth + 1, ltor); }
/** * Get a child by its name or path. * * @param name element name or path/to/element * @return the first matching element or null if no match */ public XML getChild(String name) { if (name.length() > 0 && name.charAt(0) == '/') { throw new IllegalArgumentException("getChild() should not begin with a slash"); } if (name.indexOf('/') != -1) { return getChildRecursive(PApplet.split(name, '/'), 0); } int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { XML kid = getChild(i); String kidName = kid.getName(); if (kidName != null && kidName.equals(name)) { return kid; } } return null; }
/** * Get any children that match this name or path. Similar to getChild(), but will grab multiple * matches rather than only the first. * * @param name element name or path/to/element * @return array of child elements that match * @author processing.org */ public XML[] getChildren(String name) { if (name.length() > 0 && name.charAt(0) == '/') { throw new IllegalArgumentException("getChildren() should not begin with a slash"); } if (name.indexOf('/') != -1) { return getChildrenRecursive(PApplet.split(name, '/'), 0); } // if it's a number, do an index instead // (returns a single element array, since this will be a single match if (Character.isDigit(name.charAt(0))) { return new XML[] {getChild(Integer.parseInt(name))}; } int childCount = getChildCount(); XML[] matches = new XML[childCount]; int matchCount = 0; for (int i = 0; i < childCount; i++) { XML kid = getChild(i); String kidName = kid.getName(); if (kidName != null && kidName.equals(name)) { matches[matchCount++] = kid; } } return (XML[]) PApplet.subset(matches, 0, matchCount); }
/** * Internal helper function for getChild(String). * * @param items result of splitting the query on slashes * @param offset where in the items[] array we're currently looking * @return matching element or null if no match * @author processing.org */ protected XML getChildRecursive(String[] items, int offset) { // if it's a number, do an index instead if (Character.isDigit(items[offset].charAt(0))) { XML kid = getChild(Integer.parseInt(items[offset])); if (offset == items.length - 1) { return kid; } else { return kid.getChildRecursive(items, offset + 1); } } int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { XML kid = getChild(i); String kidName = kid.getName(); if (kidName != null && kidName.equals(items[offset])) { if (offset == items.length - 1) { return kid; } else { return kid.getChildRecursive(items, offset + 1); } } } return null; }
/** * Loads the syntax as specified in the XML * * @param xml */ public void loadSyntax(XML xml) { // Get the list of defined styles XML[] styleList = xml.getChild("styles").getChildren(); for (XML style : styleList) { // Make sure that this is a "style" element if (!style.getName().equals("style")) continue; // Parse the style TextPaint paint = new TextPaint(getPaint()); String name = style.getContent(); String hex = style.getString("color", "#FF000000").substring(1); boolean bold = style.getString("bold", "false").equals("true") ? true : false; // Build the TextPaint paint.setStyle(TextPaint.Style.FILL); paint.setColor(PApplet.unhex(hex)); paint.setFakeBoldText( bold); // TODO what does "fake" mean? Is this something we should be concerned about? // Add the style styles.put(name, paint); } // Get the list of defined keywords XML[] keywords = xml.getChild("keywords").getChildren(); ArrayList<Keyword> tempSyntax = new ArrayList<>(); syntax = new Keyword[keywords.length]; for (int i = 0; i < keywords.length; i++) { XML keyword = keywords[i]; // Make sure that this is a "keyword" element if (!keyword.getName().equals("keyword")) continue; // Parse the keyword String style = keyword.getString("style", ""); String name = keyword.getContent(); boolean function = keyword.getString("function", "false").equals("true"); String reference = keyword.getString("reference", "processing"); boolean noUnderscore = keyword.getString("reference_hint", "").equals("no_underscore"); String parentClass = keyword.getString("class", ""); boolean staticInParentClass = Boolean.valueOf(keyword.getString("static", "false")); // If there is a parent class, then open that class... we don't know how to be fancier yet // Automatically add an underscore if the keyword is a function and doesn't have the // "no_underscore" hint String referenceTarget = keyword.getString( "reference_target", parentClass.length() > 0 ? parentClass : (name + (function && !noUnderscore ? "_" : ""))); // If this isn't a valid style, bail out if (!styles.containsKey(style)) continue; // Add the keyword tempSyntax.add( new Keyword( name, styles.get(style), function, reference, referenceTarget, parentClass, staticInParentClass)); } syntax = new Keyword[tempSyntax.size()]; // We need to do this because more than the half of the reported XML elements are null for (int i = 0; i < tempSyntax.size(); i++) { syntax[i] = tempSyntax.get(i); } syntaxLoaded.set(true); }