Dokka APIs Available
API docs for Doodle are now available at https://nacular.github.io/doodle-api/
Features
New PopupManager
You can now present top-level Views that will cover all other existing ones in a safe and reliable way using the new PopupManager. Before, you could make custom popups by directly adding items to the Display. This worked in many cases, but had a lot of limitations. For example, Views added this way would be affected by any Layout on the Display, which meant you couldn't control these Popups as easily. Also, new Views added to the Display after a custom popup was shown could overlay the popup. So there was no way to guarantee that a popup remained the top-most View. The new PopupManager fixes these limitations and provides a simple API for showing popups.
popupManager.show(view) {
// size / position popup
it.height eq parent.height / 2
it.width eq it.height * 1.5
it.center eq parent.center
}Popups can be positioned relatvie to another View as well by doing the following.
popups.show(view, relativeTo = someView) { popup, someViewRect ->
// size / position popup
(popup.top eq someViewRect.y ) .. Strong
(popup.left eq someViewRect.right + 10) .. Strong
(popup.bottom lessEq parent.bottom - 5) .. Strong
popup.top greaterEq 5
popup.left greaterEq 5
popup.right lessEq parent.right - 5
popup.height eq parent.height / 2
popup.width eq popup.height * 1.5
}Any View Can Be A Popup
The PopupManager's API works with View, so you can make anything a popup. Simply do the following:
popupManager.show(myView) {
it.center eq parent.center
}
// ...
popupManager.hide(myView)Views that are shown as popups will automatically become top-level (being removed from their existing parent if already displayed) and sit above all other existing Views. Hiding a popup removes it from the Display, but it won't return the View to a previous parent if it had one.
Popup Layouts
Popups are shown with layout information directly. There are two ways to show a popup: relative to the Display, or relative to another View and the Display. There is an API call for each:
Here, myView is positioned with only a "reference" to the Display (parent).
popupManager.show(myView) {
it.center eq parent.center
}But sometimes a popup needs to be positioned relative to another View. This shows how to place myView so it tracks the bounds of someView. The PopupManager will handle keeping the popup aligned with someView.
// myView is positioned with only a "reference" to the Display (parent)
popupManager.show(myView, relativeTo = someView) { popup, anchor ->
popup.top greaterEq 0 // Popup top-left always visible
popup.left greaterEq 0 // Popup top-left always visible
popup.width.preserve // don't shrink popup
popup.height.preserve // don't shrink popup
(popup.right lessEq parent.right ) .. Strong // stay in parent as long as doesn't compress popup
(popup.bottom lessEq parent.bottom) .. Strong // stay in parent as long as doesn't compress popup
(popup.top eq anchor.bottom + 10) .. Medium // follow anchor, as long as stronger constraints not in conflict
(popup.centerY eq anchor.centerY ) .. Medium // follow anchor, as long as stronger constraints not in conflict
}New ModalManager
Modals are now easy to incorporate into your apps with the help of the new ModalManager. This component uses the PopupManager to display Views that behave like modals (they require user input to be dismissed). Modals are strongly typed and return a single value upon completion. They also have a customizable overlay that will obscure the underlying Views if painted.
// launch modal and await result (suspending)
val value: T = modalManager {
Modal(
// View used as modal
view {
// ...
// call completed when the modal is done
completed(result)
}
) {
// optionally provide a layout block
// or the view will default to being
// displayed in the center
}
}Modals can also be positioned relative to another View.
// launch modal and await result (suspending)
val value: T = modalManager {
RelativeModal(
// View used as modal
view {
// ...
// call completed when the modal is done
completed(result)
},
relativeTo = someView
) { modal, someViewBounds ->
// position relative to parent and someView
}
}More Powerful Text Rendering
Text Alignment
There is a new TextAlignment enum that controls how wrapped text is displayed within its margins. This is a replacement for HorizontalAlignment, which currently uses Left, Right (instead of Start, End) and does not support Justify. You can justify text by doing the following:
canvas.wrapped(
text,
at = Origin,
width = width,
alignment = TextAlignment.Justify,
fill = Black.paint
)
canvas.wrapped(
styledText,
at = Origin,
width = width,
alignment = TextAlignment.Justify,
)Letter, Word, And Line Spacing
You can now control the way letters, words and lines are spaced when rendering text (via Canvas.text(...) and Canvas.wrapped(...)). Letter and words spacing can be provided to the text rendering methods on Canvas using the new TextSpacing class. This information can also be passed to TextMetrics when measuring text. Label also has support for both letter and word spacing.
Line spacing can also be specified whenever you deal with wrapped text.
New LazyPhoto Widget
This new component (in controls lib) takes a Deferred<Image> and renders it when loading is complete. It also takes a custom renderer that it uses to draw itself while loading. This allows customization and even animation.
APIs
Rectangle.toPaththat allows specifying each corner radius- Exposing
insetsinsimpleTextButtonRendererfunction repeatandloopanimations can now have delaysCanvascan now render wrapped text with custom line-spacingLabelnow haslineSpacingproperty which controls how it displays wrapped text- Animatable Properties are no longer restricted to use within Views
- New method to create
EllipseandCircleby inscribing within Rectangle - New
Circle.diameterproperty - New constructor for StyledText that takes a
StringandStyle - Updated parameters in
Canvas.wrappedmethods to make clearer (i.e.indent/widthvsleftMargin/rightMargin) - Added new
StyledTextVisualizerto mapStyledText->Label - Deprecated
TextVisualizerand introducedStringVisualizer defaultLayoutinNamedConfig(labeled form control) now takes an optional itemHeight- New
tableCellEditorDSL
Accessibility
- Browser
Buttonnow setsaccessibilityLabelto itstextif no label is already providedHyperLinkwith native behavior will now apply aria-label to the anchor tag using the HyperLink's text when theAccessibilityManageris present
Fixes | Improvements
- General
- Bug with empty AnimationBlock when created during active animation
- Wrapped text not correctly aligned
- Bug in FilteredList
iterator.remove - CommonLabelBehavior no longer provides an x offset for wrapped text since the alignment is handled correctly by Canvas
- Edge case where layout can hang b/c of double imprecision
- Issue where
CommonLabelBehavioroverridesLabel.foregroundColoron uninstall - Bug where incorrect item could be removed from
RenderManagerImpl.pendingLayout - Bug where some View properties lost during behavior install
- Bug where some views not cleaned up by RenderManager
- Bug in pointer handling when Display transformed
- ToggleButton no longer relies on being displayed to listen to its model
- StyledText.text now returns correct value
behaviordelegate now re-renders theViewwhen a newbehavioris installed. This removes the need for Behaviors to callrenderexplicitly upon install- Bug where
DynamicListwould have incorrect selection when selection set before items added
- Browser
- Misidentifying elements as native scroll panels led to incorrect pointer behavior
- Reuse instances for linear/radial gradient paints
- Reusing clipped images
- Hyperlinks now open in new tab
- Shadow render bug when using SVG
- Element sometimes not reused when drawing shadow
- Remove overflow on element w/ shadow
- Fixed wrapped StyledText rendering
- Wrapped StyledText now supports text decoration on previously unsupported cases
- Wrapped text no longer indents if the indent would result in the first word overflowing the width
- Issue where reused text element could retain wrapped styles
- Issue where text background color isn't properly cleared
- Cleaning up text-alignment for reused
<b>elements - Issue where styled text width not properly cleared
- Desktop
- Fixed SVG image file loading issue
- Fixed rendering of images with radius
- Issue where font families weren't being properly tracked and therefore incorrectly applied
- Incorrect paragraph width measurement
Versions
- Dokka -> 1.8.10
- Skiko -> 0.7.44