Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

405
LINES

< > BotCompany Repo | #1015892 // DynModule [base class for dynamic modules]

JavaX fragment (include) [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (21700L/133K).

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<S, Collection<S>> mechLists;
  Map<S, Bool> _persistenceInfo;
  
  transient O _host; // pointer to this module's stem
  
  transient Map<O, IVF1> timers = newWeakHashMap(); // all kinds of resources actually; value is closer helper
  transient Set<AutoCloseable> _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<S> 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<voidfunc(S field)>
  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 extends AutoCloseable> A ownResource(A a) {
    if (a != null)
      _resources.add(a);
    ret a;
  }
  
  <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> 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<S, Bool> _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<S> r) {
    lock lock;
    if (onFieldChange == null) onFieldChange = synchroList();
    addIfNotThere(onFieldChange, r);
  }
  
  void removeFieldChangeListener(VF1<S> 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<? extends JComponent> l, O r) {
    main onChangeAndNow(l, r);
  }
  
  void onChangeAndNow(JTextComponent c, IVF1<S> r) {
    onUpdateAndNow(c, r);
  }
  
  /*static*/ <A extends JComponent> A onChange(A tc, O r) {
    onUpdate(tc, r);
    ret tc;
  }

  void update() {}
  
  void unvisualize() {
    zeroAllFieldsOfTypeExcept(this, Component, componentFieldsToKeep);
  }
  
  // return L<AbstractAction> (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<S> 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> 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

download  show line numbers  debug dex  old transpilations   

Travelled to 21 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, jozkyjcghlvl, lnbujpyubztb, lpdgvwnxivlt, mowyntqkapby, mqqgnosmbjvj, onxytkatvevr, podlckwnjdmb, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt, whxojlpjdney, xrpafgyirdlv

No comments. add comment

Snippet ID: #1015892
Snippet name: DynModule [base class for dynamic modules]
Eternal ID of this version: #1015892/209
Text MD5: c95ad31395a8a070f3a4e65f3ef67ccf
Transpilation MD5: 8972aaca8849675a75c5e8660f0cad59
Author: stefan
Category: javax / stefan's os
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-07-16 00:32:14
Source code size: 11278 bytes / 405 lines
Pitched / IR pitched: No / No
Views / Downloads: 1352 / 5459
Version history: 208 change(s)
Referenced in: #1019849 - Loadable Utils
#1029927 - Loadable Utils v2 (old)
#1030952 - Loadable Utils for Gazelle BEA [LIVE, see #1030953, edited by #1030951]
#1031186 - Loadable Utils v5
#1032272 - Loadable Utils for Gazelle BEA [backup]
#1032708 - Secret BEA Utils [purposely different from regular utils]
#1033505 - Loadable Utils for Gazelle V [stable version]
#1033861 - Loadable Utils for Gazelle 22 [dev version]
#1034167 - Standard Classes + Interfaces (LIVE, continuation of #1003674)