Skip to content

0.10.2

Latest
Compare
Choose a tag to compare
@pusolito pusolito released this 28 Jun 08:34
· 1 commit to master since this release

Features

Animation Chaining

Animations can now be chained within an animation block using the new then method. This makes it easier to have sequential animations and avoids the need to explicitly track secondary animations for cancellation, since these are tied to their "parent" animation.

val animation = animate {
    0f to 1f using (tweenFloat(easing, duration)) {                   // (1)
        // ...
    } then {
        0f to 1f using (after(delay, tweenFloat(easing, duration))) { // (2)

        } then {                                                      // (3)
            // ...
        }
    } then {                                                          // (4)
        // ...
    }
}

animation.completed += { /* ... */ }  // applies to entire chain
animation.pause ()                    // applies to entire chain
animation.cancel()                    // applies to entire chain

Improved Accessibility

Desktop Support

Doodle's web apps have had accessibility support for some time. Now those capabilities are available for desktop apps as well. You simply include the AccessibilityModule in your app and follow the guidelines of how to add roles, labels, etc. to your Views.

SpinButton Accessibility

SpinButtons now use the new SpinButtonRole that allows assistive tools to better read them. This role exposes the currently selected value based on a new valueAccessibilityLabeler function that converts the value to a String.

Improved Sliders

Arbitrary Types

Sliders can now represent values of any Comparable type T between two start and end values. This is possible for Ts that have some interpolation between a start and end based on some value between 0 and 1. This is done via a new TypeConverter<T> that defines the interpolation (and its inverse).

This means you can now create sliders for numeric types like Measure<T> directly and their value will by of the right type.

val charSlider     = Slider('A' .. 'Z')
val velocitySlider = Slider(10 * meters / seconds .. 100 * miles / hours)

You can also create Sliders for any type T, as long as it is Comparable and you can create an Interpolator for it.

fun <T: Comparable<T>> customSlider(model: ConfinedValueModel<T>, interpolator: Interpolator<T>) {
    val slider: Slider<T> = Slider(model, interpolator = interpolator)
}

These, more flexible Sliders can also be used in forms as expected.

 Form {this(
    + slider('A' .. 'Z'),
    + slider(10 * meters/seconds .. 10 * miles/hours),
    + slider(model, interpolator = interpolator),
    onInvalid = {}
) { _: Char, _: Measure<Velocity>, _: T ->

}}

Non-linearity

Sliders are linear by default, which means a change in their position translates to a linear change in their value. There are cases however, when it makes sense to have a slider's value change in a non-linear way. You can do this by providing a function that maps values between the slider's input and output spaces. These values are all within the [0-1] domain, and work very similarly to easing functions used for animations. The big difference is they have two forms: f(x) and f^-1(x).

import io.nacular.doodle.controls.range.InvertibleFunction
import io.nacular.doodle.controls.range.Slider
import kotlin.math.log
import kotlin.math.pow

/**
 * Logarithmic function and inverse https://www.desmos.com/calculator/qq59ey0bub
 */
private object LogFunction: InvertibleFunction {
    override fun invoke (value: Float) = log((10f - 1) * value + 1, 10f)
    override fun inverse(value: Float) = (10f.pow(value) - 1)/(10 - 1)
}

val logarithmicSlider = Slider(0.0 .. 1.0, function = LogFunction)

APIs

  • General

    • New after animation function that allows a delay before executing an AnimationPlan.
    • Made Scene a public type since it is part of the public API for Theme
    • New builders for creating Sliders for Char and Measure<T>
    • New increment and decrement methods for sliders
    • New methods for incrementing/decrementing start/end for RangeValueSlider
    • Renamed Spinner to SpinButton (and related classes) and deprecated all old uses.
    • New SpinButtonRole for accessibility.
    • ThemePicker now allows customization of accessible value labels via new valueAccessibilityLabeler property.
    • ListItemRole now has a selected state. ListItem (BasicTheme) now keeps this value up-to-date.
    • New circumference extension for Circle
    • New helper for calculating the interior angle between two Vector3D instances.
    • New form methods for creating SpinButton form controls from a List of values or IntProgression.
    • New functions for creating ease[In/Out]Bounce EasingFunctions with an initialBounceFraction: easeIn(0.15f).
    • New convenience methods for working with PathBuilders using x,y instead of Point.
  • Deprecations

    • All animation functions that take a delay, since there is a new after function.
    • Types and functions related to Spinner, which was renamed to SpinButton.
    • Types and functions related to Dropdown, which was renamed to SelectBox.

Fixes | Improvements

  • General

    • Issue where item could be stuck in render loop if it requires a layout, but cannot render b/c it is not recursively visible (it and all ancestors visible).
  • Browser

    • Fixed issue with Display pointer exit not being properly handled.
    • Work-around for Safari giving incorrect clientX/Y values when the browser window is zoomed, which broke pointer location.
    • Fixed edge case where old rendered vectors aren't cleaned up if a sub-frame happens where one wasn't before.
    • Fixed bug in reading items from DataTransferItemList that broke file drag-drop

Versions

  • Kotlin -> 1.9.23
  • Kover -> 0.8.1
  • Dokka -> 1.9.20