Model relay rules should respond to priority directives
Description
Environment
Activity

Antranig Basman February 19, 2016 at 12:36 PM
The discussion above isn't enough to resolve all the problems here. We also need some new ways of encoding changes delivered as transactions. In order to deliver the full user experience above, we need to be able to issue the following update as a transactional unit -
i) change the value of "step" to its new value
ii) update all the other coordinates such that the real coordinate that the mouse's current "x" position is hovering over stays the same
It seems unlikely that we'll be in a position to encode the above in any way other than writing a dedicated function to issue "change" requests to enact it - the problem currently is even worse in that we can't even express the constraints above as relay rules because of lack of priority control - and also our current idiom for demarking transactions is very cumbersome. Here's the current code managing this:
where "rescalePosition" ends up being notified by the following sequence:
the "grainIndex" update eventually feeds through to an update of "dataRange.step" which invokes the above:
and finally the scrollbar subcomponent definition itself:
Note the use of pre-FLUID-5695 style priorities to control repaint vs invalidation model listeners.
We need to ensure the following:
1) The entire update triggered by zoom should trigger as a single transaction.
2) We must be able to express "positionToVis" as a relay rule
We need to recover what exactly is being referred to in the comment "autoinvalidate - a relay rule can't depend on any model state in a non-live way" but it is believed that this would be solved by having a priority order between relay rules. The issue is that the function body issues a read of "dataRange" and "position" manually. If this was a relay rule, the reference to "position", "dataRange" and its "step" would be part of its relay specification, and so it could never observe a configuration which hadn't attempted to update the scrollbar-mediated relationships between these.
When the model relay system was designed, it was considered adequate that relay rules would flood the skeleton in a purely data-driven way, and that to arbitrate between them would just lead to confusion - and a lack of well-definedness in the final stabilised skeleton state.
However, after FLUID-5361 and more experience, it's clear that this is actually exactly what is required, and it is in fact essential in order to ensure that the skeleton can settle to the user-defined state. The disorderliness of dataflow systems when there are multiple valid arcs along which updates can flow is well-known (for example, in user environments such as Quartz Composer, where relative dataflow order cannot be controlled), and since our priority system is now so mature and so well-understood, it is a reasonable economy to extend it to relay rules as well as all the other artefacts to which it applies (model listeners, distributions, context awareness rules, etc.)
Here is the motivating use case. A user component showing a graph has a "viewport", which for the sake of simplicity we will only consider the x-axis component of. This has various model coordinates associated with it, with various constraints:
We have the following constraints:
Now - as a UI action, when the user zooms in or out of the window, we need to maintain the constraint that the value of "midPoint" (or more ambitiously, any chosen real coordinate, for example, the one that the mouse x position identifies) should remain fixed during the zoom. Now, the zoom is actually "honoured" by making a change to the value of one of the "step" entries. But how is the system to determine which of the constraints which get invalidated by this is to be restored first? Choosing the final, visWindow, constraint, will not only produce the wrong result (for example, by causing the window start or end position to be maintained rather than the midpoint) but will also sufficiently pollute the pool of state that the desired configuration could never be recovered.
This implies that we need to be able to signal that, for example, the system is to react to a change in "step" in the first instance with a definitely chosen rule rather than picking a constraint in which the value appears at random. In this case, the "midpoint" rule would result in a custom propagation based on inverting some of the above constraints:
After we have successfully updated one determining element in the cooperating set, flooding propagation from this site will inevitably lead to the right result. Without the power to specify that this rule must take priority over all those in which "step" appears when processing an update, we can't ensure that the user receives the correct final model state.