// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only

/*!
    \page quick-logic-helpers.html
    \previouspage quick-design-effects.html
    \nextpage quick-animations.html

    \title Logic helpers

    To have your UI perform certain operations, you might need to write
    JavaScript expressions for conditions or convert numbers to strings.
    To make this easier, \QDS provides a set of components called
    \e {logic helpers}.

    \image studio-logic-helpers.png "Logic Helper component in Components"

    Logic helpers are available for binding property values using the boolean
    AND, NOT, and OR operators, as well as for mapping numbers and numerical
    ranges. In addition, you can synchronize the property values of two
    components bi-directionally.

    Logic helpers are invisible components that you can use in connection with
    controls, such as a \l {slider-control}{Slider} or \l {Check Box}.
    To use a logic helper, drag it from \uicontrol Components >
    \uicontrol {Qt Quick Studio Logic Helper} to \l Navigator. If you cannot
    find the logic helpers in \uicontrol {Components}, you need to add the
    \uicontrol {Qt Quick Studio Logic Helper} module to your project,
    as described in \l {Adding and Removing Modules}.

    The following sections describe the different types of logic helpers in more
    detail.

    \section1 Boolean helpers

    You can use logic helpers to bind property values using the boolean AND, OR,
    and NOT operators.

    \section2 AND Operator

    The \uicontrol {And Operator} component evaluates two boolean inputs.
    The output is evaluated as \c true if both inputs are \c true.

    For example, we could use the checked state of two check boxes to determine
    the checked state of a third one. First, we drag three instances of
    the \uicontrol {Check Box} components and one instance of the
    \uicontrol {And Operator} component to \uicontrol Navigator (1). Then, we
    select the \uicontrol {And Operator} component instance (2) and set its
    properties in \l Properties (3).

    We select \imageactionicon
    next to the \uicontrol {Input 01} field to display the \uicontrol Actions
    menu, and then \uicontrol {Set Binding} (4) to open the
    \uicontrol {Binding Editor} (5). There we bind the value of the \c input01
    property of the AND operator to the value of the \c checked property of the
    first check box. Then, we do the same in the \uicontrol {Input 02} field,
    where we bind the \c input02 property to the \c checked property of the
    second check box.

    \image studio-logic-helper-and.png "AND operator properties"

    Finally, we select the third check box and bind its \uicontrol Checked
    property to the \uicontrol Output property of the AND operator.

    \image studio-logic-helper-and-checkbox3.png "Binding Checked property to Output property."

    When we \l{Previewing on desktop}{preview} our UI, all the check boxes are
    initially unchecked. However, when we select the first and second check box,
    the third one also becomes checked.

    \image studio-logic-helper-and-operator.gif "Previewing AND operator"

    \section2 OR Operator

    The \uicontrol {Or Operator} component does the same as the AND operator,
    but the output is \c true if one or both inputs are \c true.

    \section2 NOT Operator

    The \uicontrol {Not Operator} component is evaluated to \c true if the
    condition is not met.

    For example, we could specify that if one check box is checked, another
    one cannot be checked. First, we drag two instances of the
    \uicontrol {Check Box} component and one instance of the
    \uicontrol {Not Operator} component to \uicontrol Navigator. Then, we select
    the \uicontrol {Not Operator} component instance and set its properties in
    \uicontrol Properties. In the \uicontrol {Binding Editor}, we bind the
    value of the \c input property of the NOT operator to the value of the
    \c checked property of one check box instance.

    \image studio-logic-helper-not.png "NOT operator properties"

    We then select the other check box instance and bind the value of its
    \uicontrol Checked field to the value of \uicontrol Output
    field of the \uicontrol {Not Operator} component.

    \image studio-logic-helper-not-check-box.png "Check box checked property bound to NOT operator output"

    When we preview our UI, the second check box is initially selected. However,
    when we select the first check box, the second one is automatically cleared.

    \image studio-logic-helper-not-operator.gif "Previewing two check boxes bound with a NOT operator"

    \section1 Bi-Directional Binding

    The \uicontrol {Bi Direct. Binding} component binds the values of two
    controls together, so that when one value is changed, the other one
    follows it. This component could be used to synchronize two sliders or
    a slider and checkbox. Typically, it is used to bind a backend value
    to a control, such as a slider.

    For example, to synchronize the values of two sliders, we drag two
    instances of the \uicontrol Slider component and one instance of the
    \uicontrol {Bi Direct. Binding} component to the same parent component in
    \uicontrol Navigator. Then, we select the bi-directional binding instance
    and set its properties in \uicontrol Properties.

    \image studio-logic-helper-bidirectional-binding.png "Bi-directional binding properties"

    In the \uicontrol {Target 01} and \uicontrol {Target 02} fields, enter
    the IDs of the components that you want to bind together. In the
    \uicontrol {Property 01} and \uicontrol {Property 02} fields, enter the
    names of the properties to synchronize. In our example, we bind the
    \c value property of two slider components together, so that when we move
    one slider handle in the preview, the other one moves along with it.

    \image studio-bidirectional-binding.gif "Previewing a bi-directional binding of two sliders"

    If you want to add a text field that displays the value of the slider, you
    can use a \l {String Mapper} component.

    \section1 String Mapper

    The \uicontrol {String Mapper} component maps numbers to strings. First, you
    \l{Adding bindings between properties}{add a binding} between the string
    mapper \c input property and the \c value property of the control that you
    want to fetch the values from. Then, you add a binding between the \c text
    property of the string mapper and that of the component that will display
    the string.

    For example, to use a \l Text component to display the value of a
    slider, we drag \uicontrol Text, \uicontrol Slider, and
    \uicontrol {String Mapper} components to the same parent component. Then,
    we select the \uicontrol {String Mapper} instance in \uicontrol Navigator
    to display its properties in \uicontrol Properties. There we bind the value
    of the \uicontrol Input field to the value of the \c value property of the
    \uicontrol Slider instance.

    \image studio-logic-helper-string-mapper-input.png "Binding slider value property to string mapper"

    Next, we select the \uicontrol Text instance and bind the value of the
    \uicontrol Text field to the value of the \uicontrol {Output text} field
    (\c text property) of the \uicontrol {String Mapper} component.

    \image studio-logic-helper-string-mapper-text.png "Binding text property value to string mapper"

    When we move the slider handle in the preview, the value displayed in the
    text component changes accordingly.

    \image studio-logic-helper-string-mapper.gif "Previewing text property binding to string mapper"

    The value of the \uicontrol {Decimal places} field determines the number
    of digits after the decimal separator.

    \section1 Minimum-Maximum Mapper

    The \uicontrol {Min Max Mapper} component has output values even if the
    input value is out of range. This enables you to apply actions to values,
    such as changing a color in a state, even if they are below the minimum
    value or above the maximum value.

    To access the values of a control, bind the \uicontrol Input property of
    the minimum-maximum mapper to that of the \c value property of the control.

    For example, to restrict the maximum value of a slider to 0.60,
    regardless of the maximum value set in the slider properties,
    we drag a \uicontrol {Min Max Mapper} to our example
    above. We select it to display its properties in \uicontrol Properties.
    Then, we bind the value of the \uicontrol Input property of the mapper to
    the value of the \c value property of the slider and set the value
    of the \uicontrol Max field to 0.60.

    \image studio-logic-helper-minmax-mapper-input.png "Binding slider value property to string mapper"

    To have the maximum value displayed by the \l Text component, we select
    the \uicontrol {String Mapper} component and change the binding we set
    as the value of the \uicontrol Input field from \c slider.value to
    \c minMaxMapper.output.

    \image studio-logic-helper-minmax-mapper-string-mapper-input.png "Binding string mapper input to min max mapper"

    When we move the slider handle in the preview, it only moves up to the
    value 0.60.

    \image studio-logic-helper-minmax-mapper.gif "Previewing a minimum-maximum mapper"

    The \uicontrol {Out of range}, \uicontrol {Above max} and
    \uicontrol {Below min} check boxes are set to \c true if
    the value of the \uicontrol Input field is out of range.

    For example, in the context of speed, \uicontrol {Above max} being
    \c true would mean \e {too fast}, whereas \uicontrol {Below min}
    being \c true, would mean \e {too slow}, and \uicontrol {Out of range}
    being \c true would mean \e {either too fast or too slow}.

    \section1 Range Mapper

    The \uicontrol {Range Mapper} component maps a numerical range to another
    range, so that the output value of the second range follows the input value
    of the original range. This is useful when remapping the current frame on
    the timeline, for example.

    \image studio-logic-helper-range-mapper-properties.png "Range Mapper properties"

    Specify the minimum and maximum input and output values in the
    \uicontrol {Input min}, \uicontrol {Input max},
    \uicontrol {Output min}, and \uicontrol {Output max} fields
    and the original value in the \uicontrol Output field.

    For example, we can specify that the values of a slider range from 0 to 1.
    If we want to display values from 10 to 100, instead, we can bind the
    values of the \uicontrol From and \uicontrol To fields of the \l Slider
    component to the values of the \uicontrol {Input min} and
    \uicontrol {Input max} fields of a \uicontrol {Range Mapper} component.
    We then set the value of the \uicontrol {Output min} field to 10 and the
    value of the \uicontrol {Output max} field to 100.

    \image studio-logic-helper-range-mapper-inputmin.png "Binding range mapper minimum input to slider.from property"

    When we move the slider handle in the preview, so that the input value
    from the \l Slider component changes from 0 to 1, the output value changes
    from 10 to 100.

    \image studio-logic-helper-range-mapper.gif "Previewing a range mapper"

    \section1 Combining several logic helpers

    You can combine several logic helpers of the same type or different types to
    define the application logic.

    For example, we create a small application for selling a commodity. We
    use a \uicontrol {Range Mapper} component to set the price range and
    \uicontrol {Min Max Mapper} components to create a \c blockedRange where the
    price is either too low or too high and a \e badValueRange where the price
    is under or over the going value. We then use \uicontrol {And Operator}
    components to determine whether the value is below minimum or above maximum.

    \image studio-logic-helper-combining-example.gif

    We use one \uicontrol {String Mapper} component to map the
    slider value to a \uicontrol Text component that displays the price, as
    instructed in \l{String Mapper}.

    To define a price range from 0 to 1000, we bind the \uicontrol Input
    property of the \uicontrol {Range Mapper} component to the slider value
    and set the maximum input value for the price range in the
    \uicontrol {Input max} field to 1000. The minimum input value is 0
    by default, so we don't need to change it.

    \image studio-logic-helper-combining-example-rm.png "Range Mapper properties"

    Next, we use two \uicontrol {Min Max Mapper} components to create a
    \e {blocked range} where the sell button will be hidden and a
    \e {bad value range} where selling is discouraged by changing the
    text and color of the sell hint.

    For the blocked range, we bind the \uicontrol Input property of
    the minimum-maximum mapper to the \uicontrol Output value of the
    \uicontrol {Range Mapper} component and specify the maximum input
    value in the \uicontrol Max field.

    \image studio-logic-helper-combining-example-mmm-blocked.png "Blocked range mapper properties"

    We use two \uicontrol {And Operator} components to determine that
    the sell button should be hidden when the value is in the blocked
    range. We do this by binding the value of the \uicontrol {Input 02}
    field to an evaluation of the value of \uicontrol {Out of range} field
    of the minimum-maximum mapper. We specify that when the value is not
    out of range, it evaluates to \e true.

    \image studio-logic-helper-combining-example-ao1.png "Under value minimum-maximum mapper Input 02"

    For the \e underValueAnd operator, we additionally bind the value of the
    \uicontrol {Input 01} field to the value of the \uicontrol {Below min}
    field of the minimum-maximum mapper for the bad value range. For the
    \e overValueAnd operator, we bind it to the value of the
    \uicontrol {Above max} field of the same mapper.

    \image studio-logic-helper-combining-example-ao2.png "Under value minimum-maximum mapper Input 01"

    We can now evaluate values of the \uicontrol {Min Max Mapper}
    and \uicontrol {And Operator} components to apply different
    \l{Applying states}{states} that display different button text
    and sell hints. For this purpose, we create the states and set
    \c when conditions for them.

    \image studio-logic-helper-combining-example.png

    First, we create a \e tooLow state and set a \c when condition to
    apply it when the value of the \uicontrol {Below min} field of
    the \uicontrol {Min Max Mapper} component for the blocked range
    evaluates to \c true.

    \image studio-logic-helper-combining-example-states-toolow.png "Setting when condition of tooLow state"

    For the \e tooHigh state at the other end of the scale, we set the \c when
    condition to apply it when the value of the \uicontrol {Above max} field
    of the \uicontrol {Min Max Mapper} component for the blocked range evaluates
    to \c true.

    Next, we specify that the \e underValue state is applied when
    the value of the \uicontrol Output field of the \e underValueAnd
    \uicontrol {And Operator} component evaluates to \c true.

    \image studio-logic-helper-combining-example-states-undervalue.png "Setting when condition of underValue state"

    For the \e overValue state, we set the \c when condition to apply it when
    the value of the \uicontrol Output field of the \e overValueAnd component
    evaluates to \c true.

    When we preview our application, we can see the states applied when the
    slider value changes.

    \omit
    \\TODO: Add link to video when it becomes available.

    For more information, watch the following video.

    \youtube
    \endomit

    \section1 Summary of the logic helper components

    The following table summarizes the available logic helpers.

    \table
    \header
        \li Icon
        \li Logic helper
        \li Description
    \row
        \li \imagelcandoperator16px
        \li And Operator
        \li Boolean AND.
    \row
        \li \imagelcbidirectionalbinding16px
        \li Bi Direct. Binding
        \li A bi-directional binding that binds two values in both directions
            and keeps them in sync.
    \row
        \li \imagelcminmax16px
        \li Min Max Mapper
        \li Maps a number to another number with a minimum and maximum value.
    \row
        \li \imagelcnotoperator16px
        \li Not Operator
        \li Boolean NOT.
    \row
        \li \imagelcoroperator16px
        \li Or Operator
        \li Boolean OR.
    \row
        \li \imagelcrangemapper16px
        \li Range Mapper
        \li Maps a numerical range to another range, so that the output value
            of the second range follows the input value of the original range.
    \row
        \li \imagelcstringmapper16px
        \li String Mapper
        \li Maps a number to a string with the defined precision.
    \endtable
*/
