please include function myInnerClasses. static abstract class DynModule extends DynamicObject is Enterable, ChangeTriggerable ifdef DynModule_NewChangeEvent , IHasChangeListeners endifdef { // we really shouldn't have used up these variable names // (subclasses can't overload them due to how the persistence works) S name, toolTip; // module name, module tool tip in task bar PersistableThrowable _error; Map> mechLists; Map _persistenceInfo; transient O _host; // pointer to this module's stem transient Map timers = newWeakHashMap(); // all kinds of resources actually; value is closer helper transient Set _resources = synchroHashSet(); transient Lock lock; // set by stem transient bool persistOnChangedField = true; transient int changeCount; transient new O changeCountSync; transient L onChange; transient L onTransientChange; transient bool verboseTimers; transient ReliableSingleThread rstUpdate; transient Set componentFieldsToKeep; // TODO: use DynamicObject for this transient MapSO transientGeneralMap = synchroHashMap(); transient Q q; // module command queue transient L onFieldChange; // also for non-persistent fields. L transient bool _hasPreviousBounds; transient new StringBuffer _printLog; transient bool deleted; *() { if (useErrorHandling()) dm_initErrorHandling(); // TODO: DynModule is now shared between modules, so not good setMainDesktopPane((JDesktopPane) getCreatorOpt('desktop)); } bool useErrorHandling() { true; } bool isVisible() { ret isTrue(getOpt(_host, 'visible)); } S moduleName() { ret name; } void setModuleName(S name) { S oldName = this.name; if (!eq(name, oldName)) { setField(+name); possiblyInternalFrameTitle(vis(), name); vmBus_send('moduleNameChange, this, oldName, name); } } void setModuleToolTip(S toolTip) { this.toolTip = toolTip; } JComponent vis() { ret (JComponent) getOpt(_host, 'vis); } A ownResource(A a) { if (a != null) _resources.add(a); ret a; } A ownTimer(A timer) { if (timer cast AutoCloseable) ownResource(timer); else ownTimer(timer, lambda1 cancelTimerOrInterruptThread); ret timer; } void ownTimer(O timer, IVF1 closerHelper) { timers.put(timer, closerHelper); } void singleTimer(java.util.Timer timer) { stopAllTimers(); ownTimer(timer); } void stopAllTimers() { for (AutoCloseable resource : getAndClearList(_resources)) { if (verboseTimers) print("Releasing resource: " + resource); pcall { resource.close(); } } for (O timer, IVF1 closerHelper : getAndClearMap(timers)) { if (verboseTimers) print("Stopping timer: " + closerHelper + " / " + timer); pcallF(closerHelper, timer); } } bool isDeleted() { ret deleted; } bool deleted() { ret deleted; } void cleanMeUp_dynModule { set deleted; dispose q; stopAllTimers(); } void persistMe { synchronized(changeCountSync) { ++changeCount; } pcallFAll(onChange); callOpt(_host, '_change); updateMe(); } void fireChangeWithoutPersisting { pcallFAll(onChange); } void fireTransientChange { pcallFAll(onTransientChange); } final void _change { persistMe(); } final public void change { persistMe(); } void updateMe { rstUpdate().trigger(); } void changeAndUpdate { _change(); updateMe(); } bool setField_noPersist(S name, O value) { ret setField(name, value, true); } bool _setField(S name, O value) { ret setField(name, value); } bool setField(S name, O value, bool noPersist default false) { temp enter(); pcall { // some really weird classes fail on equals() (BCEL JavaClass, I'm looking at you) if (eq(get(this, name), value)) false; } ret setField_noCheck(name, value, noPersist); } // always set even if equal bool setField_noCheck(S name, O value, bool noPersist default false) enter { //set(this, name, value); setOpt(this, name, value); // XXX allow virtual fields pcallFAll(onFieldChange, name); // XXX - new check for transient field if (!noPersist && dm_isPersistentField(me(), name)) _change(); true; } A setFieldAndReturn(S name, A value) { setField(name, value); ret value; } bool setFields(O... params) { bool change = false; for (int i = 0; i < l(params); i += 2) if (setField((S) params[i], params[i+1])) change = true; ret change; } void start { _hasPreviousBounds = dm_getBounds() != null; if (hasMethod_onTypes(this, 'onTopInput, S)) dm_onTopInput_q(voidfunc(S s) { call(module(), 'onTopInput, s) }); } void revisualize { call(dm_os(), 'revisualizeModule, _host); } bool useEnterShortcut() { false; } public AutoCloseable enter() { AutoCloseable c = tempSetBetterThreadLocalIfNecessary_weakRef(dm_current_generic_tl(), this); /// XXX shortcut, testing now (doesn't seem to work yet) if (c == null && useEnterShortcut()) null; // assume we are entered (so the rest of what we do in this function is also done) O realMC = getMainClass(this); if (printToModule()) c = combineAutoCloseables(c, tempInterceptPrintIfNotIntercepted(_printToModuleInterceptor())); if (realMC != mc()) { if (printToModule()) c = combineAutoCloseables(c, (AutoCloseable) callOpt(realMC, 'tempInterceptPrintIfNotIntercepted, _printToModuleInterceptor())); else c = combineAutoCloseables(c, tempInterceptPrintIfNotIntercepted(func(S s) -> bool { ret false with call(realMC, 'print, s); })); c = combineAutoCloseables(c, tempSetTL(realMC_tl(), realMC)); } ret c; } F1 _printToModuleInterceptor() { ret func(S s) -> bool { if (print_preprocess != null) s = (S) callF(print_preprocess, s); s = fixNewLines(s); Appendable loc = _printLog; Appendable buf = print_log; int loc_max = print_log_max; if (buf != loc && buf != null) { print_append(buf, s, print_log_max); loc_max = local_log_max; } if (loc != null) print_append(loc, s, loc_max); if (printAlsoToSystemOut) System.out.print(s); false; }; } bool printToModule() { true; } // on by default now AutoCloseable enterAndLock() { ret combineAutoCloseables(enter(), tempLock(lock)); } bool setError(Throwable e) { setField(_error := persistableThrowable(e)); true; } void clearError { setField(_error := null); } ifdef DynModule_NewChangeEvent public selfType onChange(Runnable r) { lock lock; if (onChange == null) onChange = synchroList(); addIfNotThere(onChange, r); this; } public selfType removeChangeListener(Runnable r) { remove(onChange, r); this; } endifdef ifndef DynModule_NewChangeEvent void onChange(Runnable r) { lock lock; if (onChange == null) onChange = synchroList(); addIfNotThere(onChange, r); } public void removeChangeListener(Runnable r) { remove(onChange, r); } endifndef void onFieldChange(VF1 r) { lock lock; if (onFieldChange == null) onFieldChange = synchroList(); addIfNotThere(onFieldChange, r); } void removeFieldChangeListener(VF1 r) { remove(onFieldChange, r); } ifndef DynModule_NewChangeEvent void onChangeAndNow(Runnable r) { onChange(r); callF(r); } endifndef // forward to main class void onChangeAndNow(JComponent c, O r) { onUpdateAndNow(c, r); } void onChangeAndNow(L l, O r) { main onChangeAndNow(l, r); } void onChangeAndNow(JTextComponent c, IVF1 r) { onUpdateAndNow(c, r); } /*static*/ A onChange(A tc, O r) { onUpdate(tc, r); ret tc; } void update() {} void unvisualize() { zeroAllFieldsOfTypeExcept(this, Component, componentFieldsToKeep); } // return L (legacy) // or litobjectarray(text, Runnable, text, Runnable, ...) O menuItems() { null; } void enhanceFrame(Container f) { ifndef NoMenuItems O items = menuItems(); if (items instanceof O[]) items = paramsToAbstractActions((O[]) items); internalFramePopupMenuFromActions_threaded(f, (L) items); endifndef ifndef NoSwitchableFields S switchableFields = cast callOpt(this, 'switchableFields); Set set = asLinkedHashSet(splitAtSpace(switchableFields)); new Matches m; for (S field : allFields(getClass())) if (startsWith(field, "_switchableField_", m)) set.add(m.rest()); for (S field : set) { Class type = fieldType(this, field); if (eq(bool.class, type)) dm_boolFieldMenuItem(f, field); else if (eq(int.class, type)) dm_intFieldMenuItem(f, field); else if (eq(long.class, type)) dm_longFieldMenuItem(f, field); else if (eq(double.class, type)) dm_doubleFieldMenuItem(f, field); else if (eq(float.class, type)) dm_floatFieldMenuItem(f, field); else if (eq(S, type)) dm_stringFieldMenuItem(f, field); else if (eq(File.class, type)) dm_fileFieldMenuItem(f, field); } endifndef } // assume this is called in start(), so no locking ReliableSingleThread rstUpdate() { if (rstUpdate == null) rstUpdate = dm_rst(this, r enter { update(); }); ret rstUpdate; } Q q() enter { if (q == null) { lock lock; if (q == null) q = dm_startQ(); } ret q; } A withUpdate(A a) { rstUpdate().trigger(); ret a; } DynModule module() { this; } DynModule me() { this; } JComponent visualize() { ret dm_noVisualisation(); } S programTitle_cache; S programTitle() { if (programTitle_cache == null) programTitle_cache = snippetTitle(programID(mainClass(this))); ret programTitle_cache; } // field must be non-transient void doPersist(S field) { _persistenceInfo = mapMinus(_persistenceInfo, field); } void dontPersist(S field) { _persistenceInfo = mapPlus(_persistenceInfo, field := false); } Appendable _actualPrintLog() { ret printToModule() ? _printLog : print_log; } O getHost() { ret _host; } !include #1031423 // DynModule convenience methods } // end of DynModule static void _registerTimer(java.util.Timer timer) { _registerTimer_original(timer); var mod = dm_currentModule(); mod?.ownTimer(timer); } !include once #1023504