Search code examples
javafxreactive-programmingfrpundo-redoreactfx

Add EventStream of dynamically created object changes to UndoManager


Using the UndoFX library, I create an UndoManger as follows:

EventStream<DocumentChange<?>> changes = document.getChanges();

undoManager =
  UndoManagerFactory.unlimitedHistoryUndoManager(
    changes,
    c -> c.redo(),
    c -> c.undo(),
    (c1, c2) -> c1.mergeWith(c2)
  );

The ReactFX EventStream returned by the document is created by merging a number of EventStreams which are available at document creation. For example,

documentChanges = EventStreams.merge(selectedSymbolChanges, symbolListChanges);

However, the document gets items added to it later, and those items include EventStreams that should also be published to the document EventStream. I've tried

documentChanges = EventStreams.merge(documentChanges, newObjectChanges);

However, changes in the newObjectChanges EventStream never hit the UndoManager.

What is the best way to merge additional EventStreams into the UndoManger after it is already created? Or is this impossible (i.e., stream must be immutable)?

If the latter is the case, how does one create a stream for a dynamic number of objects that don't exist at UndoManager creation time?


Solution

  • There are two ways to go about this.

    1. Create an ObservableSet of event streams and use EventStreams.merge(ObservableSet) to dynamically merge all streams from the set. You can then dynamically add/remove streams to/from the set.

    2. Use a ConnectableEventStream as a placeholder and later connect it to dynamically obtained streams:

      ConnectableEventStream<DocumentChange<?>> dynamicChanges =
              new ConnectableEventSource<>();
      
      EventStream<DocumentChange<?>> documentChanges =
              EventStreams.merge(staticChanges, dynamicChanges);
      
      // later
      dynamicChanges.connectTo(newObjectChanges1);
      dynamicChanges.connectTo(newObjectChanges2);