Notes on Selection
Selection in GUI
Selecting a View that represents a Stripable in the editor does two things:
- the View is added to the GUI side selection model for that component (Editor/Mixer)
- the underlying Stripable (if any) has its PresentationInfo marked as selected
::set_selected()
method called on it. This
will eventually invoke AxisView::set_selected()
(since all views are ultimately AxisViews). If the View
represents a Stripable, then the Stripable will have its
PresentationInfo member marked as selected. This will in turn
cause the emission
of PresentationInfo::PropertyChange
for the
affected Stripable, with the what_changed
argument
indicating a selection change. Individual views (GUI or control
surface "strips") that want to track selection status for the
Stripable that they represent will have registered a handler for
this signal. The handler (or any other code) can check the
selected status via the Stripable's PresentationInfo state.
After this, the View is actually added to the GUI side selection
model. This process may add additional Views representing
Stripables that share selection (e.g. via a RouteGroup) with the
one initially being added. Note
that ::set_selected()
is not called on these Views,
which would cause a recursive (and potentially expensive to
halt) re-entrant loop. In all other ways, these Stripables'
state will be modified as if ::set_selected()
had
been called.
Once adding all relevant Views is
complete, Selection::TracksChanged
is emitted. This
signal will be handled by both the Editor and the Mixer
component of the UI, to ensure that ::set_selected
has been invoked all appropriate View objects in both
components. This ensures that the Editor, Mixer and
PresentationInfo models of selected state remain consistent.
Next ControlProtocol::StripableSelectionChanged
will be emitted. All control surfaces that care about overall
selection status have a handler for this signal. This handler
will note the new set of selected Stripables and ensure that the
surface's version of that (which might potentially only involve
a single Stripable) is synchronized with it. A surface may opt
not to use this signal but instead use the
PresentationInfo::PropertyChange signal and other logic to
maintain the surface support code's selection model.
Finally, the Editor will
call ControlProtocol::set_first_selected_stripable()
to ensure that any control surfaces can determine
the first selected stripable. This matters for surfaces
with only a single fader, for example.
If the selection process took place in the Mixer, the steps
taken are more or identical with what is described above, except
that AxisViewSelection::RoutesChanged
is emitted
and handled by the Editor to keep the two selection models in
sync.
Note that the Editor's selection model contains many more object types than the Mixer's. The former may contain automation data, control points, track views, regions and more; the latter contains only axis views and processors.
Selection from a Control Surface
The code that supports a given surface/protocol should emit one
of the following
signals: ControlProtocol::{Add,Set,Toggle}StripableSelection
. This
signal will be handled by the Editor GUI component, which will
then carry out a selection modification as if it were driven
from Editor itself.
Note that surfaces should not set a Stripable's PresentationInfo selected status directly.
Object Deletion
The View object representing a Stripable is responsible for handling a DropReferences signal from the Stripable (indicating that it is about to be deleted). It needs to do this for many reasons, but one of them is so that it can remove itself from any Selection model that it may be a part of. So, for example, a RouteTimeAxisView representing a Stripable that has just sent DropReferences must ensure the the Editor's selection model no longer includes the RouteTimeAxisView. The same process applies to MixerStrips.
Control surface elements require similar handling of DropReferences, and are thus also responsible for ensuring the consistency of any local selection state in the control surface code for a given device/protocol.