Revision control
++ // Copyright (C) 2017 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
++
++ /*!
++ \page qmlstatemachine-qml-guide.html
++ \title Qt State Machine QML Guide
++ \brief Overview of the Qt State Machine QML for constructing and executing state graphs.
++ \ingroup technology-apis
++ \ingroup explanation
++
++ Qt State Machine QML APIs provide types for creating and
++ executing state graphs in QML. It is similar to the C++ State Machine
++ framework based on Harel's
++ \l{Statecharts: A visual formalism for complex systems}, which
++ is also the basis for UML state diagrams. Like its
++ \l{Qt State Machine C++ Classes}{C++ counterpart}, the framework provides an
++ API and execution model based on \l{State Chart XML: State Machine Notation for
++ Control Abstraction}{State Chart XML (SCXML)}
++ to embed the elements and semantics of statecharts in QML applications.
++
++ For user interfaces with multiple visual states, independent of the
++ application's logical state, consider using QML States and Transitions.
++
++ For the full list of QML types provided by the framework to create event-driven
++ state machines, see: \l {Qt State Machine QML Types}
++
++ \section1 Using Both QtQuick and QtQml.StateMachine Imports
++
++ \warning If you're attempting to import both \l[QML]{QtQuick} and
++ \e{QtQml.StateMachine} in one single QML file, make sure to import
++ \e{QtQml.StateMachine} \e{last}. This way, the \e{State} type is provided
++ by the Declarative State Machine Framework and not by \l[QML]{QtQuick}:
++
++ \qml
++ import QtQuick
++ import QtQml.StateMachine
++
++ StateMachine {
++ State {
++ // okay, is of type QtQml.StateMachine.State
++ }
++ }
++ \endqml
++
++ Alternatively, you can import \e{QtQml.StateMachine} into a separate
++ namespace to avoid any ambiguity with \l[QML]{QtQuick}'s \e{State} item:
++
++ \qml \QtMinorVersion
++ import QtQuick
++ import QtQml.StateMachine as DSM
++
++ DSM.StateMachine {
++ DSM.State {
++ // ...
++ }
++ }
++ \endqml
++
++ \section1 A Simple State Machine
++
++ To demonstrate the core functionality of the State Machine API, let's look
++ at an example: A state machine with three states, \c s1, \c s2 and \c
++ s3. The state machine is controlled by a single Button; when the button
++ is clicked, the machine transitions to another state. Initially, the state
++ machine is in state \c s1. The following is a state chart showing the
++ different states in our example.
++
++ \image statemachine-button.png
++ {Three states s1, s2, s3 cycling on button.clicked transitions}
++
++ The following snippet shows the code needed to create such a state machine.
++
++ \snippet qml/statemachine/statemachine-button.qml 0
++
++ The state machine runs asynchronously to become part of your application's
++ event loop.
++
++ \section1 State Machines That Finish
++
++ The state machine defined in the previous section never finishes. In order
++ for a state machine to be able to finish, it needs to have a top-level \e
++ final state (FinalState object). When the state machine enters the top-level
++ final state, the machine emits the \l{State::finished}{finished}
++ signal and halts.
++
++ All you need to do to introduce a final state in the graph is create a
++ FinalState object and use it as the target of one or more transitions.
++
++ \section1 Sharing Transitions
++
++ Assume we wanted the user to be able to quit the application at any time by
++ clicking a Quit button. In order to achieve this, we need to create a final
++ state and make it the target of a transition associated with the Quit
++ button's \e clicked() signal. We could add a transition for each state;
++ however, this seems redundant and one would also have to
++ remember to add such a transition from every new state that is added in the
++ future.
++
++ We can achieve the same behavior (namely that clicking the Quit button quits
++ the state machine, regardless of which state the state machine is in) by
++ grouping states \c s1, \c s2 and \c s3. This is done by creating a new
++ top-level state and making the three original states children of the new
++ state. The following diagram shows the new state machine.
++
++ \image statemachine-button-nested.png
++ {State s1 containing three substates s11, s12, s13 cycling on
++ button.clicked transitions}
++
++ The three original states have been renamed \c s11, \c s12 and \c s13 to
++ reflect that they are now childrens of the new top-level state, \c s1. Child
++ states implicitly inherit the transitions of their parent state. This means
++ it is now sufficient to add a single transition from \c s1 to the final
++ state, \c s2. New states added to \c s1 will automatically inherit this
++ transition.
++
++ All that's needed to group states is to specify the proper parent when the
++ state is created. You also need to specify which of the child states is the
++ initial one (the child state the state machine should enter when the
++ parent state is the target of a transition).
++
++ \snippet qml/statemachine/statemachine-button-nested.qml 0
++
++ In this case we want the application to quit when the state machine is
++ finished, so the machine's \e finished() signal is connected to the
++ application's \e quit() slot.
++
++ A child state can override an inherited transition. For example, the
++ following code adds a transition that effectively causes the Quit button to
++ be ignored when the state machine is in state, \c s12.
++
++ \snippet qml/statemachine/statemachine-button-nested-ignore-quit.qml 0
++
++ A transition can have any state as its target irrespective of where the
++ target state is in the state hierarchy.
++
++ \section1 Using History States
++
++ Imagine that we wanted to add an "interrupt" mechanism to the example
++ discussed in the previous section; the user should be able to click a button
++ to have the state machine perform some non-related task, after which the
++ state machine should resume whatever it was doing before (i.e. return to the
++ old state, which is one of the three states in this case).
++
++ Such behavior can easily be modeled using \e{history states}. A history
++ state (HistoryState object) is a pseudo-state that represents the child
++ state that the parent state was in before it exited last.
++
++ A history state is created as a child of the state for which we wish to
++ record the current child state; when the state machine detects the presence
++ of such a state at runtime, it automatically records the current (real)
++ child state when the parent state exits. A transition to the history
++ state is in fact a transition to the child state that the state machine had
++ previously saved; the state machine automatically "forwards" the transition
++ to the real child state.
++
++ The following diagram shows the state machine after the interrupt mechanism
++ has been added.
++
++ \image statemachine-button-history.png
++ {State s1 with substates and history state, interrupt button
++ transitions to s3, which returns to s1 history when finished}
++
++ The following code shows how it can be implemented; in this example we
++ simply display a message box when \c s3 is entered, then immediately return
++ to the previous child state of \c s1 via the history state.
++
++ \snippet qml/statemachine/statemachine-button-history.qml 0
++
++ \section1 Using Parallel States
++
++ Assume that you wanted to model a set of mutually exclusive properties of a
++ car in a single state machine. Let's say the properties we are interested in
++ are Clean vs Dirty, and Moving vs Not moving. It would take four mutually
++ exclusive states and eight transitions to represent the states and freely
++ move between all possible combinations as shown in the following state chart.
++
++ \image statemachine-nonparallel.png
++ {Four states: clean/not moving, clean/moving, dirty/not moving,
++ dirty/moving with started, stopped, cleaned, soiled transitions}
++
++ If we added a third property (say, Red vs Blue), the total number of states
++ would double, to eight; and if we added a fourth property (say, Enclosed vs
++ Convertible), the total number of states would double again, to 16.
++
++ This exponential increase can be reduced using parallel states, which enables
++ linear growth in the number of states and transitions as we add more
++ properties. Furthermore, states can be added to or removed from the parallel
++ state without affecting any of their sibling states. The following state
++ chart shows the different paralles states for the car example.
++
++ \image statemachine-parallel.png
++ {Parallel state s1 with regions s11 (clean/dirty) and s12
++ (moving/not moving)}
++
++ To create a parallel state group, set childMode to QState.ParallelStates.
++
++ \qml
++ State {
++ id: s1
++ childMode: QState.ParallelStates
++ State {
++ id: s11
++ }
++ State {
++ id: s12
++ }
++ }
++ \endqml
++
++ When a parallel state group is entered, all its child states will be
++ simultaneously entered. Transitions within the individual child states
++ operate normally. However, any of the child states may take a transition
++ which exits the parent state. When this happens, the parent state and all of
++ its child states are exited.
++
++ The parallelism in the State Machine framework follows an interleaved
++ semantics. All parallel operations will be executed in a single, atomic step
++ of the event processing, so no event can interrupt the parallel operations.
++ However, events will still be processed sequentially, as the machine itself
++ is single threaded. For example, consider the situation where there are two
++ transitions that exit the same parallel state group, and their conditions
++ become true simultaneously. In this case, the event that is processed last
++ of the two will not have any effect.
++
++ \section1 Exiting a Composite State
++
++ A child state can be final (a FinalState object); when a final child state
++ is entered, the parent state emits the State::finished signal. The
++ following diagram shows a composite state \c s1 which does some processing
++ before entering a final state:
++
++ \image statemachine-finished.png
++ {State s1 with processing substate transitioning to final state,
++ triggering move to s2}
++
++ When \c s1 's final state is entered, \c s1 will automatically emit
++ \l{State::finished}{finished}. We use a signal transition to cause this event to
++ trigger a state change:
++
++ \qml
++ State {
++ id: s1
++ SignalTransition {
++ targetState: s2
++ signal: s1.finished
++ }
++ }
++ \endqml
++
++ Using final states in composite states is useful when you want to hide the
++ internal details of a composite state. The outside world should be able to
++ enter the state and get a notification when the state has completed its work,
++ without the need to know the internal details. This is a very powerful
++ abstraction and encapsulation mechanism when building complex (deeply nested)
++ state machines. (In the above example, you could of course create a transition
++ directly from \c s1 's \c done state rather than relying on \c s1 's
++ finished() signal, but with the consequence that implementation details of
++ \c s1 are exposed and depended on).
++
++ For parallel state groups, the State::finished signal is emitted when \e
++ all the child states have entered final states.
++
++ \section1 Targetless Transitions
++
++ A transition need not have a target state. A transition without a target can
++ be triggered the same way as any other transition; the difference is that
++ it doesn't cause any state changes. This allows you to react to a signal or
++ event when your machine is in a certain state, without having to leave that
++ state. For example:
++
++ \qml
++ Button {
++ id: button
++ text: "button"
++ StateMachine {
++ id: stateMachine
++ initialState: s1
++ running: true
++ State {
++ id: s1
++ SignalTransition {
++ signal: button.clicked
++ onTriggered: console.log("button pressed")
++ }
++ }
++ }
++ }
++ \endqml
++
++ The "button pressed" message will be displayed each time the button is clicked, but the
++ state machine will remain in its current state (s1). If the target state
++ were explicitly set to s1, s1 would be exited and re-entered each
++ time (the QAbstractState::entered and QAbstractState::exited
++ signals would be emitted).
++
++ \section1 Related Information
++
++ \list
++ \li \l{Qt State Machine QML Types}
++ \li \l{Qt State Machine Overview}
++ \endlist
++ */