Search code examples
libreoffice-calclibreoffice-basic

How to create a fade in effect on the selection?


Regarding macros, there's very few done with Impress (no record of macros, no Python scripting, only Basic etc.), and very few samples.

There's no sample how to create "manually" a text animation. I've found one here (6 years old) and there's a lot of information.

So far I've managed to (1) scan for a text animation "fadein" that is already there (2) scan for all other text animations, and then remove them an replace them by a clone of the "fadein" animation:

sub MyFunction
    ' --------------------------------------------------------------------
    ' (1) scan for a text animation "fadein" that is already there
    effectNodeFadeIn = Null
    doc = ThisComponent
    numSlides = doc.getDrawPages().getCount()
    slide = doc.drawPages(numSlides-1)

    mainSequence = getMainSequence(slide)    
    clickNodes = mainSequence.createEnumeration()
    while clickNodes.hasMoreElements() and IsNull(effectNodeFadeIn)
        clickNode = clickNodes.nextElement()

        groupNodes = clickNode.createEnumeration()
        while groupNodes.hasMoreElements() and IsNull(effectNodeFadeIn)
            groupNode = groupNodes.nextElement()

            effectNodes = groupNode.createEnumeration()
            while effectNodes.hasMoreElements() and IsNull(effectNodeFadeIn)
                effectNode = effectNodes.nextElement()
                ' ICIC

                if effectNode.ImplementationName = "animcore::ParallelTimeContainer" then
                    if hasUserDataKey(effectNode, "preset-id") then
                        v = getUserDataValue(effectNode, "preset-id")
                        if v = "ooo-entrance-fade-in" then ' ooo-entrance-appear
                            effectNodeFadeIn = effectNode
                        end if
                    end if
                end if
                ' useless loop just in case I need it:
                animNodes = effectNode.createEnumeration()
                while animNodes.hasMoreElements()
                    animNode = animNodes.nextElement()
                wend
            wend
        wend
    wend
    ' --------------------------------------------------------------------
    ' (2) scan for all other text animations, 
    ' and then remove them an replace them by a clone of the "fadein" animation
    if not IsNull(effectNodeFadeIn) then

        clickNodes = mainSequence.createEnumeration()
        while clickNodes.hasMoreElements()
            clickNode = clickNodes.nextElement()

            groupNodes = clickNode.createEnumeration()
            while groupNodes.hasMoreElements()
                groupNode = groupNodes.nextElement()

                effectNodes = groupNode.createEnumeration()
                while effectNodes.hasMoreElements()
                    effectNode = effectNodes.nextElement()
                    ' ICIC

                    if effectNode.ImplementationName = "animcore::ParallelTimeContainer" then
                        if hasUserDataKey(effectNode, "preset-id") then
                            v = getUserDataValue(effectNode, "preset-id")
                            if v <> "ooo-entrance-fade-in" then ' ooo-entrance-appear
                                groupNode.removeChild(effectNode)
                                n = effectNodeFadeIn.createClone()
                                groupNode.appendChild(n)

                                ' useless loop just in case I need it:
                                animNodes = effectNode.createEnumeration()
                                while animNodes.hasMoreElements()
                                    animNode = animNodes.nextElement()
                                wend
                            end if
                        end if

                    end if
                wend
            wend
        wend
    end if
end sub

function hasUserDataKey(node as Object, key as String) as Boolean
    for each data in node.UserData
        if data.Name = "node-type" then
            hasUserDataKey = True
            exit function
        end if
    next data
    hasUserDataKey = False
end function

function getUserDataValue(node as Object, key as String) as Variant
    for each data in node.UserData
        if data.Name = key then
            getUserDataValue = data.Value
            exit function
        end if
    next data
end function

When I clone the effect, it's still "linked" to the original text and then the parent is removed and replaced by the "fadein" text. Any idea how to correct this?


Solution

  • It sounds like you have selected text inside of a shape, so use Basic code as follows:

    Sub AddAnimation
        xTextCursor = ThisComponent.CurrentController.Selection(0)
        xText = xTextCursor.getText()
        xText.TextEffect = com.sun.star.presentation.AnimationEffect.FADE_FROM_BOTTOM
    End Sub
    

    Or in python:

    import uno
    from com.sun.star.presentation.AnimationEffect import FADE_FROM_BOTTOM
    
    def add_animation():
        oDoc = XSCRIPTCONTEXT.getDocument()
        xTextCursor = oDoc.CurrentController.Selection.getByIndex(0)
        xText = xTextCursor.getText()
        xText.TextEffect = FADE_FROM_BOTTOM
    

    For reasons not entirely clear to me, the result is Wipe rather than Fade In.

    Documentation is at https://wiki.openoffice.org/wiki/Documentation/DevGuide/Drawings/Animations_and_Interactions. The ShapeHelper class from that page is defined in ShapeHelper.java.