Scripting FreeMind

FreeMind supports scripting in Groovy. It's cool, though definitely a new-new feature without much in the way of help. You'll need to download the FreeMind source to figure out what you can do, the example scripts on the wiki give a flavor but don't answer enough questions, and the javadocs on the site are for the old version, not for the current beta version.

Below is a script to total all the values in child nodes. For example if your nodes all have an attribute called "price", you simply install this script in an attribute called "script" on the root node (or any node for that matter), hit Alt-F8 to run the script, and if you've defined a "price-total" attribute on the node with the script, "price-total" will be filled in with the actual total of all the price attributes. This is my first real code in Groovy, so please pardon any gaffes. I defined a few helper functions, since the attributes API is a bit cranky to work with:


// Get a java.util.Map of all the attributes on a node
def attrMap = { node -> 
    def attrs = [:];
    for(i in 0..<node.getAttributes().getRowCount()) {
        attrs[node.getAttributes().getName(i)] = node.getAttributes().getValue(i);
    };
    return attrs;
};

//Get all the children of a node, regardless of how deep.
def allChildren = { node ->
    def kids = [];
    def stack = new Stack();
    stack.push(node.childrenUnfolded());
    while(!stack.isEmpty()) {
        nodes = stack.pop();
        while(nodes.hasNext()) {
						k = nodes.next();
            kids.add(k);
						stack.push(k.childrenUnfolded());
        };
    };
    return kids;
};
//find all the attributes that we're trying to total
def getTotalsMap = { node -> 
    def totals = [:];
    for(key in attrMap(node).keySet()) {
        if (key.endsWith("-total")) { 
            attributeBase = key.substring(0, key.indexOf("-total"));
            totals[attributeBase] = 0;
        };
    };
    return totals;
};

//calculate the totals
def getChildTotals = { node ->
    def totals = getTotalsMap(node);
    allChildren(node).each { kid ->
				attrMap(kid).findAll{ it.getKey() in totals.keySet() }.each { e ->
                try { 
			if (!"<error>".equals(totals[e.getKey()]))
	                    totals[e.getKey()] += new BigDecimal(e.getValue()); 
                } catch (NumberFormatException ex) { 
			totals[e.getKey()] = "<error>"; 
		};
        };    
    };
    return totals;
};

//set the totals into the node
def setTotals = { node, totals ->
    def count = node.getAttributes().getRowCount();
    for(i in 0..<count) {
        def name = node.getAttributes().getName(i);
        if (name.endsWith("total"))
            node.getAttributes().setValue(i, "total");
        for(key in totals.keySet()) {
            if (key + "-total" == name)
                node.getAttributes().setValue(i, totals[key]);
        };
    };
};

//do it!
setTotals(node, getChildTotals(node));