/* event change; => transient LinkedHashSet onChange; public selfType onChange(Runnable r) { onChange = syncAddOrCreate(onChange, r); this; } void change() { pcallFAll(onChange); } */ svoid tok_eventFunctions(LS tok) { int i; while ((i = jfind(tok, "event ")) >= 0) { int iSemicolon = i+4; LS tokArgs = null; if (eqGet(tok, i+4, "(")) { int argsFrom = i+6; int argsTo = findCodeTokens(tok, argsFrom, false, ")"); tokArgs = subList(tok, argsFrom-1, argsTo); iSemicolon = argsTo+2; } // TODO for next version: parse modifiers in square brackets //if (eqGet(tok, iSemicolon, "[")) int iEnd = iSemicolon+1; S body = ""; if (eqGet(tok, iSemicolon, "{")) { iEnd = tok_findEndOfBlock(tok, iSemicolon); body = joinSubList(tok, iSemicolon+1, iEnd-1); } else if (neqGet(tok, iSemicolon, ";")) fail("Semicolon expected at end: " + joinSubList(tok, i, iSemicolon+1)); S change = tok.get(i+2), prefix = ""; if (startsWithCamelCaseWord(change, "on")) change = firstToLower(dropFirst(2, change)); else if (startsWithCamelCaseWord(change, "fire")) { prefix = "fire"; change = firstToLower(dropFirst(4, change)); } S onChange = "on" + firstToUpper(change); S removeListener = "remove" + firstToUpper(change) + "Listener"; LPairS args = tok_typesAndNamesOfParams(tokArgs); LS types = pairsA(args); S args1 = join(dropFirstAndLast(tokArgs)); S args2 = joinWithComma(pairsB(args)); S typeParams = joinWithComma(map tok_toNonPrimitiveTypes(types)); S listenerType = empty(args) ? "Runnable" : "IVF" + l(args) + "<" + typeParams + ">"; S r = empty(args) ? "r" : "f"; S fireChange = empty(prefix) ? change : prefix + firstToUpper(change); replaceTokens_reTok(tok, i, iEnd, "transient Set<\*listenerType*/> \*onChange*/;\n" + "public selfType \*onChange*/(\*listenerType*/ \*r*/) { \*onChange*/ = createOrAddToSyncLinkedHashSet(\*onChange*/, \*r*/); this; }\n" + "public selfType \*removeListener*/(\*listenerType*/ \*r*/) { main remove(\*onChange*/, \*r*/); this; }\n" + "public void \*fireChange*/(\*args1*/) { \*body*/ pcallFAll(\*joinNemptiesWithComma(onChange, args2)*/); }" ); } }