Nick
06/21/2024, 3:04 AM0.10.2-SNAPSHOT
. Please try it out (and provide feedback) by pointing to maven { url = uri("<https://oss.sonatype.org/content/repositories/snapshots>") }
.
Here's what's included so far...
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 animate: Animator
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
Desktop Accessibility 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
`SpinButton`s 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
Sliders can now represent values of any Comparable
type T
between two start
and end
values. This is possible for `T`s 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-linear Sliders
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.20Cherrio LLC
06/21/2024, 6:06 PM