All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlinx.jupyter.api.outputs.Animate.kt Maven / Gradle / Ivy

There is a newer version: 0.12.0-335
Show newest version
package org.jetbrains.kotlinx.jupyter.api.outputs

import org.jetbrains.kotlinx.jupyter.api.Notebook
import java.util.UUID
import kotlin.time.Duration

private fun generateId() = UUID.randomUUID().toString()

/**
 * The `Frame` class represents a single frame in an animation.
 *
 * @param delayBefore The delay duration before displaying the content of the frame.
 * @param content The content of the frame. In the end, the content is passed to
 * [DisplayHandler.handleDisplay] or [DisplayHandler.handleUpdate]
 * and handled by the dedicated display handler.
 * @param T The type of the content.
 */
class Frame(
    val delayBefore: Duration,
    val content: T,
)

/**
 * Displays all the frames left in this [frames] iterator, with respect to the delays.
 *
 * @param frames An iterator over [Frame] elements to be displayed.
 * @throws InterruptedException if any thread has interrupted the current thread
 * while the current thread is waiting for the frame delays.
 */
@Throws(InterruptedException::class)
fun Notebook.animate(frames: Iterator>) {
    val displayId = generateId()
    var isFirst = true
    frames.forEachRemaining { frame ->
        val frameContent = frame.content ?: "null"
        val frameDelay = frame.delayBefore.inWholeMilliseconds
        Thread.sleep(frameDelay)
        if (isFirst) {
            display(frameContent, displayId)
            isFirst = false
        } else {
            updateDisplay(frameContent, displayId)
        }
    }
}

/**
 * Displays all the frames in this sequence, with respect to the delays.
 *
 * @param sequence A sequence of [Frame] elements to be displayed.
 */
fun Notebook.animate(sequence: Sequence>) {
    animate(sequence.iterator())
}

/**
 * Displays all the frames in this iterable, with respect to the delays.
 *
 * @param iterable Iterable of [Frame] elements to be displayed.
 */
fun Notebook.animate(iterable: Iterable>) {
    animate(iterable.iterator())
}

/**
 * Triggers the animation using a chain of frames, beginning with [firstFrame]
 * and subsequently obtained through the [nextFrame] function.
 *
 * @param firstFrame The first frame of the animation.
 * @param nextFrame Function that takes the current frame and returns the next frame,
 * or null if the animation is finished.
 */
fun  Notebook.animate(
    firstFrame: Frame,
    nextFrame: (Frame) -> Frame?,
) {
    animate(generateSequence(firstFrame, nextFrame))
}

/**
 * Triggers the animation sequence consisting of frames that are produced by the [nextFrame] function.
 *
 * @param nextFrame A function that returns the next frame in the animation sequence.
 */
fun Notebook.animate(nextFrame: () -> Frame<*>?) {
    animate(generateSequence(nextFrame))
}

/**
 * Animates a sequence of frames by displaying them with respect to their delays.
 *
 * @param framesCount The number of frames to animate.
 * @param frameByIndex A function that maps an index to a frame.
 *                     The index represents the position of the frame in the sequence.
 */
fun Notebook.animate(
    framesCount: Int,
    frameByIndex: (index: Int) -> Frame<*>,
) {
    animate(
        sequence {
            repeat(framesCount) { frameIndex ->
                yield(frameByIndex(frameIndex))
            }
        },
    )
}

/**
 * Animates a sequence of values by displaying them with specified delay.
 * The first value is displayed without a delay.
 *
 * @param delay The delay duration between each frame.
 * @param iterator An iterator over the values to be animated.
 *
 * @throws InterruptedException if any thread is interrupted while waiting for frame delays.
 */
fun Notebook.animate(
    delay: Duration,
    iterator: Iterator<*>,
) {
    animate(
        object : Iterator> {
            private var isFirst = true

            override fun hasNext(): Boolean {
                return iterator.hasNext()
            }

            override fun next(): Frame<*> {
                val content = iterator.next()
                return Frame(if (isFirst) Duration.ZERO else delay, content).also {
                    isFirst = false
                }
            }
        },
    )
}

/**
 * Animates a sequence of values with a specified delay between each frame.
 * The first value is displayed without a delay.
 *
 * @param delay The delay duration between each frame.
 * @param sequence The sequence of frames to animate.
 */
fun Notebook.animate(
    delay: Duration,
    sequence: Sequence<*>,
) {
    animate(delay, sequence.iterator())
}

/**
 * Animates a sequence of values with a specified delay between each frame.
 * The first value is displayed without a delay.
 *
 * @param delay The delay duration between each frame.
 * @param nextValue A function that provides the next value in the sequence.
 */
fun Notebook.animate(
    delay: Duration,
    nextValue: () -> Any?,
) {
    animate(delay, generateSequence(nextValue))
}

/**
 * Animates a sequence of values with a specified delay between each frame.
 * The first value is displayed without a delay.
 *
 * @param delay The delay duration between each frame.
 * @param firstValue The initial value of the sequence.
 * @param nextValue A function that generates the next value based on the current value in the sequence.
 * @param T The type of the values in the sequence.
 */
fun  Notebook.animate(
    delay: Duration,
    firstValue: T?,
    nextValue: (T) -> T?,
) {
    animate(delay, generateSequence(firstValue, nextValue))
}

/**
 * Animates an iterable sequence of values, each one (except first) appearing after a specified delay.
 *
 * @param delay The time delay to wait before displaying each frame.
 * @param iterable The set of elements to display as animation frames.
 */
fun Notebook.animate(
    delay: Duration,
    iterable: Iterable<*>,
) {
    animate(delay, iterable.iterator())
}

/**
 * Animates a sequence of values with a specified delay between each frame.
 * The first value is displayed without a delay.
 *
 * @param framesCount The number of frames to animate.
 * @param delay The delay duration between each frame.
 * @param valueByIndex The function that generates the content of each frame based on the frame index.
 */
fun Notebook.animate(
    delay: Duration,
    framesCount: Int,
    valueByIndex: (index: Int) -> Any?,
) {
    animate(
        delay,
        sequence {
            repeat(framesCount) { frameIndex ->
                yield(valueByIndex(frameIndex))
            }
        },
    )
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy