Interface Icon
- All Known Implementing Classes:
BitmapIcon,SvgIcon
Image, which is just a fixed grid of RGBA pixels for display. An icon
knows how to produce the right bitmap for a given device-pixel size
and theme brightness, and whether that bitmap is a single-color mask (recolored
with the theme) or a finished, pre-colored picture.
This split is why components take an Icon (buttons, labels, tabs,
field adornments) while style-free image widgets take a raw Image: an
icon adapts to DPI and theme, a picture does not.
Built-in implementations:
SvgIcon: vector source, rasterized crisply at any size (no up/down-sampling blur on HiDPI), tinted to the theme.BitmapIcon, one or more PNGs: a monochrome/grayscale mask to tint, light/dark variants, or per-resolution variants.
An icon may be animated (isAnimated()): a BitmapIcon of an animated
Image is. A component plays it by itself, as the image asks, through paint(limn.graphics.Canvas, float, float, float, limn.graphics.Color, boolean): its
time is the scene's, it starts at the paint that first shows it, waits where nobody sees it,
rests on its last frame once its turns are done, and asks for a frame of its window only when
one of its frames is due, repainting the icon's box and nothing more. A component offers no
control over it; an icon that must be held, sped or turned otherwise is an image view's to show. A menu shows the first frame, and so does a
window's own icon. The system's wish for less motion is not applied: an application that needs
an icon to move less ships one that moves less.
-
Nested Class Summary
Nested ClassesModifier and TypeInterfaceDescriptionstatic enumWhether an icon turns around when the interface does. -
Method Summary
Modifier and TypeMethodDescriptiondefault intdefault intframeMillis(int frame) image(int pixelSize, boolean dark) The bitmap best suited to apixelSize×pixelSizebox measured in device pixels, for the given theme brightness.default Imageimage(int pixelSize, boolean dark, int frame) One frame of the bitmapimage(int, boolean)answers, which is that method's answer for frame 0.default booleandefault intdefault voidPaints this icon into asize×sizelogical box at(x, y): it requests a bitmap at the exact device resolution (size ×Canvas.contentScale()) so the result is crisp, then appliestintwhen tintable (otherwise draws the picture untouched).default voidpaint(Canvas canvas, float x, float y, float size, @Nullable Color tint, boolean dark, boolean mirrored) Paints this icon, flipped horizontally about its own box whenmirrored.default booleantintable()Whetherimage(int, boolean)returns a single-color mask to be recolored with the theme (true: SVG, grayscale/mono PNG), or a finished picture to draw as-is (false: pre-colored light/dark variants).
-
Method Details
-
image
The bitmap best suited to apixelSize×pixelSizebox measured in device pixels, for the given theme brightness. Vector icons rasterize at exactly this size (so they stay sharp on HiDPI and at any zoom); bitmap icons pick their nearest available variant.Answers on the calling thread, and has no asynchronous form on purpose:
paint(limn.graphics.Canvas, float, float, float, limn.graphics.Color, boolean)calls it from inside a frame, and a paint that asked for a bitmap has to be given one before it can finish. An implementation whose bitmap is expensive to produce carries the warm-up on its own type instead, where the caller can run it ahead of the frame;SvgIcon.imageAsync(int)is the one that does.- Parameters:
pixelSize- target extent in physical pixels (≥ 1)dark- whether the active theme is dark (selects light/dark variants)
-
isAnimated
default boolean isAnimated()- Returns:
- whether this icon has more than one frame, which a component plays; false unless overridden
-
frameCount
default int frameCount()- Returns:
- how many frames; 1 for a still icon
-
frameMillis
default int frameMillis(int frame) - Parameters:
frame- from 0 toframeCount()- 1- Returns:
- how long that frame is shown, in milliseconds; 0 for a still icon
- Throws:
IndexOutOfBoundsException- if there is no such frame
-
loopCount
default int loopCount()- Returns:
- how many turns the animation makes: 0 for one that does not end, which is also what a still icon answers
-
image
One frame of the bitmapimage(int, boolean)answers, which is that method's answer for frame 0. A frame of an animation decoded as it plays is decoded here, on the calling thread, if it is not in memory.- Parameters:
pixelSize- target extent in physical pixels (≥ 1)dark- whether the active theme is darkframe- from 0 toframeCount()- 1- Returns:
- the frame, of the size frame 0 is
- Throws:
IndexOutOfBoundsException- if there is no such frame
-
tintable
default boolean tintable()Whetherimage(int, boolean)returns a single-color mask to be recolored with the theme (true: SVG, grayscale/mono PNG), or a finished picture to draw as-is (false: pre-colored light/dark variants). Governs whetherpaint(limn.graphics.Canvas, float, float, float, limn.graphics.Color, boolean)applies its tint. -
paint
Paints this icon into asize×sizelogical box at(x, y): it requests a bitmap at the exact device resolution (size ×Canvas.contentScale()) so the result is crisp, then appliestintwhen tintable (otherwise draws the picture untouched). This is the one idiom every component uses to draw an icon.An animated icon is drawn at the frame of the moment for the widget painting it, whose clock this call starts; the box is then taken in that widget's own coordinates, as every component paints its icons, since it is the box a due frame repaints. Painted from outside a widget's paint, it shows its first frame.
-
paint
default void paint(Canvas canvas, float x, float y, float size, @Nullable Color tint, boolean dark, boolean mirrored) Paints this icon, flipped horizontally about its own box whenmirrored.The flip is a negative x scale about the destination rect, and it is the one legal negative scale in this toolkit: it acts on a single image, never on a tree. Mirroring a layout is a placement decision taken by the widget that owns the coordinate, and a transform at any root would turn correctly shaped text into a mirror image, flip every picture and every video frame, and put an inverse transform on the hot path of every hit test.
A caller passes
mirroredasmirroring == Mirroring.IN_RTL && widget.layoutDirection() == RTL: the flag says what the icon means and the axis says which way the interface reads, and neither alone is the answer.- Parameters:
mirrored- whether to flip;falseis exactlypaint(Canvas, float, float, float, Color, boolean)
-