Skip to main content

Media & Pickers

Last stop in the Component Library, coming from Panels & Layout: images, files, and a few specialized pickers for colors and dates.

Less overlap here than earlier pages — the only real either/or is Photo vs. LazyPhoto (already loaded an Image, or not); everything else on this page does something the others don't.

Photo​

A bit of a conceptual curiosity worth knowing about: an Image in Doodle isn't actually a View — it's closer to text, something you draw directly onto a Canvas with image, as you saw back on Images. Photo is the simple wrapper that turns an already-loaded Image into a real View, so it can sit in a layout, receive a transform, or do anything else a View can do. Pair it with ImageLoader to get the Image it needs.

package controls import io.nacular.doodle.controls.Photo import io.nacular.doodle.geometry.Size import io.nacular.doodle.image.Image fun usage(image: Image) { //sampleStart Photo(image).apply { suggestSize(Size(100, 200)) } //sampleEnd }
tip

Want a Photo (or really any View) to keep its aspect ratio as it resizes? Apply the preserveAspect SizeAuditor from the Layout page — this is exactly the kind of thing that hook exists for.

LazyPhoto​

:::caution Experimental This control relies on experimental Coroutine features. :::

Where Photo needs an Image you already have in hand, LazyPhoto takes a Deferred<Image> instead — an image load that's already underway. That lets you wire up a View for an image before it's actually finished loading, with full control over what renders in the meantime: you supply the lambda that draws the loading state for as long as the Deferred is pending.

tip

Since you control that loading-state render yourself, it's a natural fit for Animation — re-render on each frame to show a spinner or pulse while the image is still in flight.

FileSelector​

Opens the system's native file picker and reports back the files the user chose — the click-to-browse counterpart to dragging files in, which you saw covered on Drag & Drop. The chosen files (a list of LocalFiles) arrive through its filesLoaded event. NativeTheme (Web, Desktop) styles it by default.

NativeFileSelectorStyler lets you swap in your own look while keeping the native file-picking behavior intact underneath — the same pattern you saw with HyperLink.

ColorPicker​

Lets the user choose an RGB Color by picking a hue and an opacity. It's built on the HSL/HSV color-space utilities mentioned back on Paint & Stroke — this is the control those utilities exist to support.

MonthPanel​

Shows a single month as a grid of days, with a date selectable from it. It deliberately doesn't show a weekday header of its own — that's DaysOfTheWeekPanel's job. Its kept separate so MonthPanel stays reusable in layouts a header would get in the way of, like a vertically scrolling calendar where the weekdays stay pinned to the top instead of scrolling past with each month.

Two properties worth knowing about: showAdjacentMonths controls whether days from the previous/next month appear grayed out to fill the grid, and weekStart sets which day the week begins on.

DaysOfTheWeekPanel​

A row of weekday labels, meant to sit alongside MonthPanel as its header — the two are built to be composed together into a full calendar view, which is exactly what the live demo shows.

tip

Stacking DaysOfTheWeekPanel above MonthPanel is a job for GridPanel or a couple of straightforward constraints — nothing calendar-specific required. See this demo for a fuller example with a vertically scrolling calendar built from a List<LocalDate> with a MonthPanel per month.

Custom Calendar​

Here's the two combined into something real: a simple vertical calendar, one column wide, built from a List<LocalDate> whose model holds the months of the current year — so the virtualized rendering and view recycling you met back on List carries over for free here too, even across a year's worth of months. Each date in the list is visualized with a small custom View pairing a Label with a MonthPanel, recycled and updated as the calendar scrolls.

The real trick is in that custom View's ItemVisualizer: it hands MonthPanel its own visualizer in turn, which is what controls each day's color and how the selected background renders — visualizers composing into further visualizers, all the way down.

Recap​

  • Images aren't Views — Photo wraps an already-loaded one into a View; LazyPhoto does the same for an in-flight Deferred<Image>, with a loading state you control.
  • FileSelector is the click-to-browse counterpart to drag-and-drop file handling, reporting files through filesLoaded.
  • MonthPanel and DaysOfTheWeekPanel are meant to be composed together into a calendar, rather than used alone — and both are configurable enough (adjacent-month display, week start day) to fit most calendar designs without a custom control.

Next: on to Forms to see several controls come together into one typed, validated unit.