!7 srecord Result(S text, S moduleID, S moduleDesc, O[] params, double value) { O coreObject() { ret optPar(params, 'additionalInfo, text); } } module QuickSearchManager > DynQuickSearch { transient S resultsQuery; transient Map> resultsByModule = synchroMap(); transient L shownResults; transient Map moduleRankings; start { //set doSearchVerbose; thread { moduleRankings = mapValues(f parseDouble, mechMap("Search Module Rankings")); } } afterVisualize { onDoubleClickOrEnter(list, r { Result r = _get(shownResults, getSelectedIndex(list)); if (r == null) ret; dm_hideQuickSearchModules(); O defaultAction = getOpt(r.coreObject(), 'defaultAction); if (defaultAction == null) defaultAction = optPar(r.params, 'defaultAction); callFInNewThread(defaultAction, r.coreObject()); }); listPopupMenu(list, voidfunc(JPopupMenu menu, S item) { final Result r = _get(shownResults, getSelectedIndex(list)); if (r == null) ret; O[] params = optPar(r.params, 'popupItems); for (int i = 0; i+1 < l(params); i += 2) { if (isMenuSeparatorIndicator(params[i])) continue with --i; fO action = params[i+1]; addMenuItem(menu, str(params[i]), r { callFInNewThread(action, r.coreObject()) }); } }); } LS calc_impl() { L results = concatLists(cloneValues(getResultsByModule(dm_topInput()))); sortByFieldDesc_inPlace(results, 'value); ret map(func(Result r) -> S { resultToText(r) }, shownResults = takeFirst(50, results)); } S resultToText(Result r) { ret "[" + r.moduleDesc + "] " + r.text; } // clear if query changed Map> getResultsByModule(S input) { synchronized(resultsByModule) { if (neq(resultsQuery, input)) { resultsQuery = input; resultsByModule.clear(); } ret resultsByModule; } } // API void setResultsForModule(S moduleID, S query, L results) { setResultsForModule(moduleID, null, query, results); } // results: LS or LPair (string to print, additional info) void setResultsForModule(fS moduleID, S _moduleDesc, S query, L results, fO... _) { fS moduleDesc = _moduleDesc != null ? _moduleDesc : dm_moduleName(moduleID); if (neq(query, dm_topInput())) ret with print("Results for wrong query: " + query); final double moduleValue = toDouble(mapGet(moduleRankings, dm_programID(moduleID))); synchronized(resultsByModule) { getResultsByModule(query).put(moduleID, map(results, func(O o) -> Result { o instanceof S ? Result((S) o, moduleID, moduleDesc, _, 0) : Result(getString(o, 'a), moduleID, moduleDesc, paramsPlus(_, additionalInfo := _get(o, 'b)), moduleValue) })); } // show/update list //if (nempty(results)) doSearch(resultsQuery); } }