!7 // manage an "unclear" list (one that varies by context), // e.g. the list of known first names srecord Entry(S name, S comment) {} cmodule UnclearList > DynObjectTable { switchable S description = "First names"; // plural of what we are storing // mech list that may contain useful items for us L> possibleMechLists = syncList(); visual jhsplit(withCenteredButtons( jCenteredSection("Current items", super), "Clear", rThreadEnter { quickBackup(); clear(); }, "Add...", rThreadEnter { JTextField tfName = jTextField(); JTextField tfComment = jTextField(); showFormTitled("Add " + itemDesc(), itemDesc(), tfName, "Comment", tfComment, r { addItem(gtt(tfName), gtt(tfComment)) }) }), withCenteredButtons( jCenteredSection("Possible lists", dm_calculatedTextArea(() -> lines(possibleMechLists))), "Clear", rThreadEnter { quickBackup(); possibleMechLists.clear(); change(); }, "Add...", rThreadEnter { dm_selectMechList("Mech list of " + description, voidfunc(S name) { addPossibleMechList(name, "") // TODO: comment }); }, "Load all lists", rThreadEnter loadAllPossibleLists)); start { dm_useFieldAsTitle description(); dm_vmBus_answerToMessage unclearListModuleOf(type -> eqic(type, description) ? dm_moduleID(module()) : null); } // API void addItem(S name, S comment) { add(new Entry(name, comment)); } void removeItem(S name) { remove(objectWhere(list(), +name)); } void addPossibleMechList(S name, S comment) { possibleMechLists.add(WithComment(comment, name)); change(); } Set itemsSet() { ret collectAsCISet name(list()); } void loadAllPossibleLists { Set known = itemsSet(); for (S listName : getAllVars(possibleMechLists)) addAll(mapNonNulls(mL(listName), x -> known.contains(x) ? null : new Entry(x, "from " + quote(listName)))); } S itemDesc() { ret singular(description); } }