AbstractDelegate.java
package swingtree;
import sprouts.Event;
import sprouts.Val;
import swingtree.animation.Animation;
import swingtree.animation.AnimationState;
import swingtree.animation.Animator;
import swingtree.animation.LifeTime;
import swingtree.api.AnimatedStyler;
import swingtree.api.Painter;
import swingtree.api.Styler;
import swingtree.layout.Bounds;
import swingtree.layout.Size;
import swingtree.style.ComponentExtension;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.border.Border;
import java.awt.*;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Extensions of this class delegate a component
* as well as provide useful methods for trying the tree of the components
* in which the delegated component is contained. <br>
* Instances of this class are passed to various user event {@link Action} handlers.
* You can use this to change the state of the component, schedule animations
* for the component or query the tree of the components.
*
* @param <C> The type of the component that is delegated.
*/
abstract class AbstractDelegate<C extends JComponent>
{
private final GuiTraverser _guiTraverser; // the traverser object that allows us to query the component tree
private final C _component;
/**
* @param component The component that is delegated.
* @param handle A component that is used as a starting point for traversing the component tree,
* usually the same component as the one that is delegated.
*/
AbstractDelegate( boolean nullable, C component, JComponent handle ) {
_guiTraverser = new GuiTraverser(Objects.requireNonNull(handle));
_component = nullable ? component : Objects.requireNonNull(component);
}
@SuppressWarnings("ReferenceEquality")
protected final boolean _isUndefinedFont( Font font ) {
return font == UI.Font.UNDEFINED;
}
@SuppressWarnings("ReferenceEquality")
protected final boolean _isUndefinedColor( Color color ) {
return color == UI.Color.UNDEFINED;
}
protected C _component() { return _component; }
protected List<JComponent> _siblingsSource() {
return Optional.ofNullable(_component.getParent())
.map(Container::getComponents)
.map(Arrays::stream)
.orElseGet(Stream::empty)
.filter(c -> c instanceof JComponent)
.map(c -> (JComponent) c)
.collect(Collectors.toList());
}
/**
* This is a delegate to the underlying component, but not every method of the component
* is delegated. This method allows you to access the underlying component directly.
* <p>
* Note that this method expects that the accessing thread is the event dispatch thread,
* not the application thread.
* If you want to access the component from the application thread, you should use <br>
* {@code UI.run(() -> delegate.component())}.
*
* @return The underlying component.
* @throws IllegalStateException If the accessing thread is not the event dispatch thread.
*/
public final C get() {
if ( !UI.thisIsUIThread() )
throw new IllegalStateException(
"You can only access the component from the GUI thread. " +
"Use 'UI.run(() -> delegate.component())' to access the component from the application thread."
);
return _component();
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently access the x-coordinate of the component relative to its parent.
*
* @return The x-coordinate of the component relative to its parent.
*/
public final int getX() { return _component().getX(); }
/**
* As a delegate to the underlying component, you can use this method to
* conveniently access the y-coordinate of the component relative to its parent.
*
* @return The y-coordinate of the component relative to its parent.
*/
public final int getY() { return _component().getY(); }
/**
* As a delegate to the underlying component, you can use this method to
* conveniently access the location of the component relative to its parent
* in the form of a {@link Point} object.
* The value returned by this method is equal to the value returned by
* {@link #getX()} and {@link #getY()}.
*
* @return The location of the component relative to its parent.
*/
public final Point getLocation() { return _component().getLocation(); }
/**
* This is class a delegate API, which means that it represents
* the API of a wrapped component. This method allows you to access
* the parent of the underlying component.
* In essence, this is a delegate to {@link Component#getParent()}. <br>
*
* @return The parent {@link Container} of the underlying component.
* @throws IllegalStateException If the accessing thread is not the event dispatch thread.
*/
public final Container getParent() {
if ( UI.thisIsUIThread() )
return _component().getParent();
else
throw new IllegalStateException(
"You can only access the parent component from the GUI thread. " +
"Use 'UI.run(() -> delegate.getParent())' to access the parent component from the application thread."
);
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the background color of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* <p>
* See {@link Component#setBackground(Color)} for more information.
* </p>
*
* @param color The color that should be used to paint the background of the component.
* If this parameter is <code>null</code> then this component will inherit
* the background color of its parent.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setBackground( Color color ) {
Objects.requireNonNull(color, "Use UI.Color.UNDEFINED instead of null to represent the absence of a color.");
if ( _isUndefinedColor(color) )
_component().setBackground(null);
else
_component().setBackground(color);
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the background color of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* <p>
* See {@link Component#setBackground(Color)} for more information.
* </p>
*
* @param r The red component of the color as a double between 0 and 1.
* @param g The green component of the color as a double between 0 and 1.
* @param b The blue component of the color as a double between 0 and 1.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setBackgroundColor( double r, double g, double b ) {
return setBackgroundColor(r, g, b, 1.0);
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the background color of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* <p>
* See {@link Component#setBackground(Color)} for more information.
* </p>
*
* @param r The red component of the color as a double between 0 and 1.
* @param g The green component of the color as a double between 0 and 1.
* @param b The blue component of the color as a double between 0 and 1.
* @param a The alpha component of the color as a double between 0 and 1.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setBackgroundColor( double r, double g, double b, double a ) {
return setBackground(new Color((float) r, (float) g, (float) b, (float) a));
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the background color of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* <p>
* See {@link Component#setBackground(Color)} for more information.
* </p>
*
* @param r The red component of the color as an integer between 0 and 255.
* @param g The green component of the color as an integer between 0 and 255.
* @param b The blue component of the color as an integer between 0 and 255.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setBackgroundColor( int r, int g, int b ) {
return setBackgroundColor(r, g, b, 255);
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the background color of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* <p>
* See {@link Component#setBackground(Color)} for more information.
* </p>
*
* @param r The red component of the color as an integer between 0 and 255.
* @param g The green component of the color as an integer between 0 and 255.
* @param b The blue component of the color as an integer between 0 and 255.
* @param a The alpha component of the color as an integer between 0 and 255.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setBackgroundColor( int r, int g, int b, int a ) {
return setBackground(new Color(r, g, b, a));
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently get the background color of the component.
* <p>
* See {@link Component#getBackground()} for more information.
* </p>
*
* @return The background color of the component, or {@link UI.Color#UNDEFINED} if the component
* does not have a background color (i.e. {@link Component#getBackground()} returns <code>null</code>).
* The return value will never be <code>null</code>.
*/
public final Color getBackground() {
Color backgroundColor = _component().getBackground();
if ( backgroundColor == null )
return UI.Color.UNDEFINED;
else
return backgroundColor;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the foreground color of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* <p>
* See {@link Component#setForeground(Color)} for more information.
* </p>
*
* @param color The color that should be used to paint the foreground of the component.
* If this parameter is <code>null</code> then this component will inherit
* the foreground color of its parent.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setForeground( Color color ) {
Objects.requireNonNull(color, "Use UI.Color.UNDEFINED instead of null to represent the absence of a color.");
if ( _isUndefinedColor(color) )
_component().setForeground( null );
else
_component().setForeground( color );
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently get the foreground color of the component.
* <p>
* See {@link Component#getForeground()} for more information.
* </p>
*
* @return The foreground color of the component, or {@link UI.Color#UNDEFINED} if the component
* does not have a foreground color (i.e. {@link Component#getForeground()} returns <code>null</code>).
* The return value will never be <code>null</code>.
*/
public final Color getForeground() {
Color foregroundColor = _component().getForeground();
if ( foregroundColor == null )
return UI.Color.UNDEFINED;
else
return foregroundColor;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the foreground color of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* <p>
* See {@link Component#setForeground(Color)} for more information.
* </p>
*
* @param r The red component of the color as a double between 0 and 1.
* @param g The green component of the color as a double between 0 and 1.
* @param b The blue component of the color as a double between 0 and 1.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setForegroundColor( double r, double g, double b ) {
return setForegroundColor(r, g, b, 1.0);
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the foreground color of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* <p>
* See {@link Component#setForeground(Color)} for more information.
* </p>
*
* @param r The red component of the color as a double between 0 and 1.
* @param g The green component of the color as a double between 0 and 1.
* @param b The blue component of the color as a double between 0 and 1.
* @param a The alpha component of the color as a double between 0 and 1.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setForegroundColor( double r, double g, double b, double a ) {
return setForeground(new Color((float) r, (float) g, (float) b, (float) a));
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the foreground color of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* <p>
* See {@link Component#setForeground(Color)} for more information.
* </p>
*
* @param r The red component of the color as an integer between 0 and 255.
* @param g The green component of the color as an integer between 0 and 255.
* @param b The blue component of the color as an integer between 0 and 255.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setForegroundColor( int r, int g, int b ) {
return setForegroundColor(r, g, b, 255);
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the foreground color of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* <p>
* See {@link Component#setForeground(Color)} for more information.
* </p>
*
* @param r The red component of the color as an integer between 0 and 255.
* @param g The green component of the color as an integer between 0 and 255.
* @param b The blue component of the color as an integer between 0 and 255.
* @param a The alpha component of the color as an integer between 0 and 255.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setForegroundColor( int r, int g, int b, int a ) {
return setForeground(new Color(r, g, b, a));
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the font of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* <p>
* See {@link Component#setFont(Font)} for more information.
* </p>
*
* @param font The font that should be used to paint the text of the component.
* If this parameter is {@link UI.Font#UNDEFINED} then this component will inherit
* the font of its parent. Null is not allowed.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setFont( Font font ) {
Objects.requireNonNull(font, "Use UI.Font.UNDEFINED instead of null to represent the absence of a font.");
if ( _isUndefinedFont(font) )
_component().setFont(null);
else
_component().setFont(font);
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently get the font of the component.
* <p>
* See {@link Component#getFont()} for more information.
* </p>
*
* @return The font of the component.
*/
public final Font getFont() {
Font font = _component().getFont();
if ( font == null )
return UI.Font.UNDEFINED;
else
return font;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the border of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* <p>
* Note that this method is a delegate to {@link JComponent#setBorder(Border)}.
* </p>
*
* @param border The border that should be used to paint the border of the component.
* If this parameter is <code>null</code> then this component will inherit
* the border of its parent.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setBorder( Border border ) {
_component().setBorder(border);
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently get the border of the component.
* <p>
* Note that this method is a delegate to {@link JComponent#getBorder()}.
* </p>
*
* @return The border of the component.
*/
public final Border getBorder() {
return _component().getBorder();
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the bounds of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* <p>
* See {@link Component#setBounds(int, int, int, int)} for more information.
* </p>
*
* @param x The x coordinate of the new location of the component.
* This is relative to the component's parent.
* @param y The y coordinate of the new location of the component.
* This is relative to the component's parent.
* @param width The new width of the component.
* @param height The new height of the component.
* @return The delegate itself, so you can chain calls to this method.
*/
public final AbstractDelegate<C> setBounds( int x, int y, int width, int height ) {
_component().setBounds(x, y, width, height);
return this;
}
/**
* Delegates to the {@link JComponent#setBounds(int, int, int, int)} method
* of the underlying component. The bounds consist of a location and a size
* which are relative to the component's parent.
*
* @param bounds The new bounds of the component.
* This is relative to the component's parent.
* @return The delegate itself, so you can chain calls to this method.
*/
public final AbstractDelegate<C> setBounds( Bounds bounds ) {
return setBounds(
(int) bounds.location().x(),
(int) bounds.location().y(),
bounds.size().width().map(Number::intValue).orElse(0),
bounds.size().height().map(Number::intValue).orElse(0)
);
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the bounds of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* <p>
* See {@link Component#setBounds(Rectangle)} for more information.
* </p>
*
* @param bounds The new bounds of the component.
* This is relative to the component's parent.
* @return The delegate itself, so you can chain calls to this method.
*/
public final AbstractDelegate<C> setBounds( Rectangle bounds ) {
_component().setBounds(bounds);
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently get the bounds of the component.
* <p>
* See {@link Component#getBounds()} for more information.
* </p>
*
* @return The bounds of the component.
* This is relative to the component's parent.
*/
public final Rectangle getBounds() {
return _component().getBounds();
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the preferred size of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The preferred size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setPreferredSize(Dimension)} for more information.
* </p>
* @param size The preferred size of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setPrefSize( Dimension size ) {
_component().setPreferredSize(size);
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the preferred size of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The preferred size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setPreferredSize(Dimension)} for more information.
* </p>
* @param size The preferred size of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setPrefSize( Size size ) {
return setPrefSize(size.toDimension());
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the preferred size of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The preferred size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setPreferredSize(Dimension)} for more information.
* </p>
* @param width The preferred width of the component.
* @param height The preferred height of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setPrefSize( int width, int height ) {
_component().setPreferredSize(new Dimension(width, height));
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the preferred width of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The preferred size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setPreferredSize(Dimension)} for more information.
* </p>
* @param width The preferred width of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setPrefWidth( int width ) {
Dimension size = _component().getPreferredSize();
_component().setPreferredSize(new Dimension(width, size.height));
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the preferred height of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The preferred size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setPreferredSize(Dimension)} for more information.
* </p>
* @param height The preferred height of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setPrefHeight( int height ) {
Dimension size = _component().getPreferredSize();
_component().setPreferredSize(new Dimension(size.width, height));
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently get the preferred size of the component.
* The preferred size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#getPreferredSize()} for more information.
* </p>
* @return The preferred size of the component.
*/
public final Size getPrefSize() {
return Size.of(_component().getPreferredSize());
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the minimum size of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The minimum size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setMinimumSize(Dimension)} for more information.
* </p>
* @param size The minimum size of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setMinSize( Dimension size ) {
_component().setMinimumSize(size);
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the minimum size of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The minimum size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setMinimumSize(Dimension)} for more information.
* </p>
* @param size The minimum size of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setMinSize( Size size ) {
Objects.requireNonNull(size, "Use Size.unknown() instead of null to represent the absence of a size.");
if ( size.equals(Size.unknown()) )
_component().setMinimumSize(null);
else
_component().setMinimumSize(size.toDimension());
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the minimum size of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The minimum size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setMinimumSize(Dimension)} for more information.
* </p>
* @param width The minimum width of the component.
* @param height The minimum height of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setMinSize( int width, int height ) {
_component().setMinimumSize(new Dimension(width, height));
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the minimum width of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The minimum size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setMinimumSize(Dimension)} for more information.
* </p>
* @param width The minimum width of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setMinWidth( int width ) {
Dimension size = _component().getMinimumSize();
_component().setMinimumSize(new Dimension(width, size.height));
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the minimum height of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The minimum size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setMinimumSize(Dimension)} for more information.
* </p>
* @param height The minimum height of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setMinHeight( int height ) {
Dimension size = _component().getMinimumSize();
_component().setMinimumSize(new Dimension(size.width, height));
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently get the minimum size of the component.
* The minimum size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#getMinimumSize()} for more information.
* </p>
* @return The minimum size of the component.
*/
public final Size getMinSize() {
return Size.of(_component().getMinimumSize());
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the maximum size of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The maximum size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setMaximumSize(Dimension)} for more information.
* </p>
* @param size The maximum size of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setMaxSize( Dimension size ) {
_component().setMaximumSize(size);
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the maximum size of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The maximum size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setMaximumSize(Dimension)} for more information.
* </p>
* @param size The maximum size of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setMaxSize( Size size ) {
Objects.requireNonNull(size, "Use Size.unknown() instead of null to represent the absence of a size.");
if ( size.equals(Size.unknown()) )
_component().setMaximumSize(null);
else
_component().setMaximumSize(size.toDimension());
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the maximum size of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The maximum size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setMaximumSize(Dimension)} for more information.
* </p>
* @param width The maximum width of the component.
* @param height The maximum height of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setMaxSize( int width, int height ) {
_component().setMaximumSize(new Dimension(width, height));
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the maximum width of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The maximum size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setMaximumSize(Dimension)} for more information.
* </p>
* @param width The maximum width of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setMaxWidth( int width ) {
Dimension size = _component().getMaximumSize();
_component().setMaximumSize(new Dimension(width, size.height));
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the maximum height of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The maximum size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setMaximumSize(Dimension)} for more information.
* </p>
* @param height The maximum height of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setMaxHeight( int height ) {
Dimension size = _component().getMaximumSize();
_component().setMaximumSize(new Dimension(size.width, height));
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently get the maximum size of the component.
* The maximum size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#getMaximumSize()} for more information.
* </p>
* @return The maximum size of the component.
*/
public final Size getMaxSize() {
return Size.of(_component().getMaximumSize());
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the size of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setSize(Dimension)} for more information.
* </p>
* @param size The size of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setSize( Dimension size ) {
_component().setSize(size);
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the size of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setSize(Dimension)} for more information.
* </p>
* @param size The size of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setSize( Size size ) {
Objects.requireNonNull(size);
_component().setSize(size.toDimension());
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the size of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setSize(Dimension)} for more information.
* </p>
* @param width The width of the component.
* @param height The height of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setSize( int width, int height ) {
_component().setSize(new Dimension(width, height));
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the width of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setSize(Dimension)} for more information.
* </p>
* @param width The width of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setWidth( int width ) {
Dimension size = _component().getSize();
_component().setSize(new Dimension(width, size.height));
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the height of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* The size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#setSize(Dimension)} for more information.
* </p>
* @param height The height of the component.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setHeight( int height ) {
Dimension size = _component().getSize();
_component().setSize(new Dimension(size.width, height));
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently get the size of the component.
* The size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#getSize()} for more information.
* </p>
* @return The size of the component.
*/
public final Size getSize() {
return Size.of(_component().getSize());
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently get the width of the component.
* The size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#getSize()} for more information.
* </p>
* @return The width of the component.
*/
public final int getWidth() {
return _component().getSize().width;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently get the height of the component.
* The size is used by the layout manager to determine the size of the component.
* <p>
* See {@link Component#getSize()} for more information.
* </p>
* @return The height of the component.
*/
public final int getHeight() {
return _component().getSize().height;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the {@link UI.Cursor} of the component.
*
* @param cursor The {@link UI.Cursor} which should be set.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setCursor( UI.Cursor cursor ) {
Objects.requireNonNull(cursor);
_component().setCursor(Cursor.getPredefinedCursor(cursor.type));
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the {@link Cursor} of the component.
* @param cursor The {@link Cursor} which should be set.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setCursor( Cursor cursor ) {
_component().setCursor(cursor);
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently get the {@link Cursor} of the component.
* @return The {@link Cursor} of the component.
*/
public final Cursor getCursor() {
return _component().getCursor();
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently set the tooltip of the component.
* This method returns the delegate itself, so you can chain calls to this method.
* <p>
* See {@link JComponent#setToolTipText(String)} for more information.
* </p>
* @param text The tooltip text.
* @return The delegate itself.
* @throws NullPointerException If the text is null, use an empty string to model the absence of a tooltip.
*/
public final AbstractDelegate<C> setTooltip( String text ) {
Objects.requireNonNull(text, "Use an empty string instead of null to represent the absence of a tooltip.");
_component().setToolTipText( text.isEmpty() ? null : text );
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently get the tooltip of the component.
* <p>
* See {@link JComponent#getToolTipText()} for more information.
* </p>
* @return The tooltip text.
*/
public final String getTooltip() {
return _component().getToolTipText();
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently enable or disable the component.
* This method returns the delegate itself, so you can chain calls to this method.
* <p>
* See {@link JComponent#setEnabled(boolean)} for more information.
* </p>
* @param enabled True if the component should be enabled, false otherwise.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setEnabled( boolean enabled ) {
_component().setEnabled(enabled);
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently check if the component is enabled.
* <p>
* See {@link JComponent#isEnabled()} for more information.
* </p>
* @return True if the component is enabled, false otherwise.
*/
public final boolean isEnabled() {
return _component().isEnabled();
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently enable or disable the component.
* This method returns the delegate itself, so you can chain calls to this method.
* <p>
* See {@link JComponent#setVisible(boolean)} for more information.
* </p>
* @param visible True if the component should be visible, false otherwise.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setVisible( boolean visible ) {
_component().setVisible(visible);
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently check if the component is visible.
* <p>
* See {@link JComponent#isVisible()} for more information.
* </p>
* @return True if the component is visible, false otherwise.
*/
public final boolean isVisible() {
return _component().isVisible();
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently make the component opaque or transparent.
* This method returns the delegate itself, so you can chain calls to this method.
* <p>
* See {@link JComponent#setOpaque(boolean)} for more information.
* </p>
* @param opaque True if the component should be opaque, false otherwise.
* @return The delegate itself.
*/
public final AbstractDelegate<C> setOpaque( boolean opaque ) {
_component().setOpaque(opaque);
return this;
}
/**
* As a delegate to the underlying component, you can use this method to
* conveniently check if the component is opaque.
* <p>
* See {@link JComponent#isOpaque()} for more information.
* </p>
* @return True if the component is opaque, false otherwise.
*/
public final boolean isOpaque() {
return _component().isOpaque();
}
/**
* Use this to query the UI tree and find any {@link JComponent}
* of a particular type and id (the name of the component).
*
* @param type The {@link JComponent} type which should be found in the swing tree.
* @param id The ide of the {@link JComponent} which should be found in the swing tree.
* @return An {@link Optional} instance which may or may not contain the requested component.
* @param <T> The type parameter of the component which should be found.
*/
public final <T extends JComponent> OptionalUI<T> find( Class<T> type, String id ) {
Objects.requireNonNull(type);
Objects.requireNonNull(id);
return this.find( type, c -> ComponentExtension.from(c).hasId(id) );
}
/**
* Use this to query the UI tree and find any {@link JComponent}
* of a particular type and id (the name of the component).
*
* @param type The {@link JComponent} type which should be found in the swing tree.
* @param id The ide of the {@link JComponent} which should be found in the swing tree.
* @return An {@link Optional} instance which may or may not contain the requested component.
* @param <T> The type parameter of the component which should be found.
*/
public final <T extends JComponent> OptionalUI<T> find( Class<T> type, Enum<?> id ) {
Objects.requireNonNull(type);
Objects.requireNonNull(id);
return this.find( type, c -> ComponentExtension.from(c).hasId(id) );
}
/**
* Use this to query the UI tree and find any {@link JComponent}
* based on a specific type and a predicate which is used to test
* if a particular component in the tree is the one you are looking for.
*
* @param type The {@link JComponent} type which should be found in the swing tree.
* @param predicate The predicate which should be used to test the {@link JComponent}.
* @return An {@link Optional} instance which may or may not contain the requested component.
* @param <T> The type parameter of the component which should be found.
*/
public final <T extends JComponent> OptionalUI<T> find( Class<T> type, Predicate<T> predicate ) {
Objects.requireNonNull(type);
Objects.requireNonNull(predicate);
return _guiTraverser.find(type, predicate)
.findFirst()
.map(OptionalUI::ofNullable)
.orElse(OptionalUI.empty());
}
/**
* Use this to query the UI tree and find all {@link JComponent}s
* based on a specific type and a predicate which is used to test
* if a particular component in the tree is the one you are looking for.
*
* @param type The {@link JComponent} type which should be found in the swing tree.
* @param predicate The predicate which should be used to test the {@link JComponent}.
* @return A list of {@link JComponent} instances which match the given type and predicate.
* @param <T> The type parameter of the component which should be found.
*/
public final <T extends JComponent> List<T> findAll( Class<T> type, Predicate<T> predicate ) {
Objects.requireNonNull(type);
Objects.requireNonNull(predicate);
return _guiTraverser.find(type, predicate).collect(Collectors.toList());
}
/**
* Use this to query the UI tree and find all {@link JComponent}s
* of a particular type and also that belong to a particular style group.
*
* @param type The {@link JComponent} type which should be found in the swing tree.
* @param group The style group which should be used to test the {@link JComponent}.
* @return A list of {@link JComponent} instances which match the given type and group.
* @param <T> The type parameter of the component which should be found.
*/
public final <T extends JComponent> List<T> findAllByGroup( Class<T> type, String group ) {
Objects.requireNonNull(type);
Objects.requireNonNull(group);
return this.findAll( type, c -> ComponentExtension.from(c).belongsToGroup(group) );
}
/**
* Use this to query the UI tree and find all {@link JComponent}s
* that belong to a particular style group.
*
* @param group The style group which should be used to check if a particular {@link JComponent} belongs to it.
* @return A list of {@link JComponent} instances which all have the given style group.
* @throws NullPointerException If the group is null.
*/
public final List<JComponent> findAllByGroup( String group ) {
Objects.requireNonNull(group);
return this.findAll( JComponent.class, c -> ComponentExtension.from(c).belongsToGroup(group) );
}
/**
* Use this to query the UI tree and find all {@link JComponent}s
* of a particular type and also that belong to a particular style group.
*
* @param type The {@link JComponent} type which should be found in the swing tree.
* @param group The style group which should be used to test the {@link JComponent}.
* @return A list of {@link JComponent} instances which match the given type and predicate.
* @param <T> The type parameter of the component which should be found.
*/
public final <T extends JComponent> List<T> findAllByGroup( Class<T> type, Enum<?> group ) {
Objects.requireNonNull(type);
Objects.requireNonNull(group);
return this.findAll( type, c -> ComponentExtension.from(c).belongsToGroup(group) );
}
/**
* Use this to query the UI tree and find all {@link JComponent}s
* that belong to a particular style group.
*
* @param group The style group which should be used to check if a particular {@link JComponent} belongs to it.
* @return A list of {@link JComponent} instances which all have the given style group.
*/
public final List<JComponent> findAllByGroup( Enum<?> group ) {
Objects.requireNonNull(group);
return this.findAll( JComponent.class, c -> ComponentExtension.from(c).belongsToGroup(group) );
}
/**
* A common use case is to render something on top of the component
* using the {@link Graphics2D} instance of the component.
* This method allows you to attach a paint task to the component, which
* the EDT will process in the next repaint event cycle, and remove when the animation expires.
* This ensures that custom rendering
* is not erased by a potential repaint of the component after a user event.
* <p>
* Here is an example of how to use this method as part of a fancy button animation:
* <pre>{@code
* UI.button("Click me").withPrefSize(400, 400)
* .onMouseClick( it -> it.animateFor(2, TimeUnit.SECONDS, state -> {
* double r = 300 * state.progress() * it.scale();
* double x = it.mouseX() - r / 2;
* double y = it.mouseY() - r / 2;
* it.paint(state, g -> {
* g.setColor(new Color(1f, 1f, 0f, (float) (1 - state.progress())));
* g.fillOval((int) x, (int) y, (int) r, (int) r);
* });
* }))
* }</pre>
* You may also be interested in doing style animations, if so, maybe consider taking a look at
* {@link UIForAnySwing#withTransitoryStyle(Event, LifeTime, AnimatedStyler)} to see how to do event based styling animations
* and {@link UIForAnySwing#withTransitionalStyle(Val, LifeTime, AnimatedStyler)} to see how to do 2 state switch based styling animations.
*
* @param state The current animation state, which is important so that the rendering can be synchronized with the animation.
* @param painter The rendering task which should be executed on the EDT at the end of the current event cycle.
*/
public final void paint( AnimationState state, Painter painter ) {
Objects.requireNonNull(state);
Objects.requireNonNull(painter);
paint(UI.ComponentArea.BODY, state, painter);
}
/**
* A common use case is to render something on top of the component
* using the {@link Graphics2D} instance of the component.
* This method allows you to attach a paint task to the component, which
* the EDT will process in the next repaint event cycle, and remove when the animation expires.
* This ensures that custom rendering
* is not erased by a potential repaint of the component after a user event. <br>
* Additionally, you can specify the area of the component which should be painted.
* <p>
* Here is an example of how to use this method as part of a button animation:
* <pre>{@code
* UI.button("Click me").withPrefSize(400, 400)
* .onMouseClick( it -> it.animateFor(2, TimeUnit.SECONDS, state -> {
* double r = 300 * state.progress() * it.scale();
* double x = it.mouseX() - r / 2;
* double y = it.mouseY() - r / 2;
* it.paint(UI.ComponentArea.BORDER, state, g -> {
* g.setColor(new Color(1f, 1f, 0f, (float) (1 - state.progress())));
* g.fillOval((int) x, (int) y, (int) r, (int) r);
* });
* }))
* }</pre>
* You may also be interested in doing style animations, if so, maybe consider taking a look at
* {@link UIForAnySwing#withTransitoryStyle(Event, LifeTime, AnimatedStyler)} to see how to do event based styling animations
* and {@link UIForAnySwing#withTransitionalStyle(Val, LifeTime, AnimatedStyler)} to see how to do 2 state switch based styling animations.
*
* @param area The area of the component which should be painted.
* @param state The current animation state, which is important so that the rendering can be synchronized with the animation.
* @param painter The rendering task which should be executed on the EDT at the end of the current event cycle.
*/
public final void paint( UI.ComponentArea area, AnimationState state, Painter painter ) {
Objects.requireNonNull(state);
Objects.requireNonNull(painter);
UI.run(()->{ // This method might be called by the application thread, so we need to run on the EDT!
// We do the rendering later in the paint method of a custom border implementation!
ComponentExtension.from(_component).addAnimatedPainter(state, UI.Layer.BORDER, area, painter);
});
}
/**
* A common use case is to animate the style of a component when a user event occurs.
* This method allows you to dispatch a styling animation to the EDT
* which will cause the component style to updated repeatedly until the animation expires.
* Because animation styles are applied last, it is guaranteed not to be overwritten by
* other {@link Styler} lambdas.
* Note that the provided styling will be removed automatically when the animation expires,
* so no manual cleanup is required.
* <p>
* Here is an example of how to use this method as part of a fancy styling animation:
* <pre>{@code
* UI.button("Click me").withPrefSize(400, 400)
* .onMouseClick( it -> it.animateStyleFor(2, TimeUnit.SECONDS, (state, style) ->
* .borderWidthAt(UI.Edge.BOTTOM, (int)(6 * state.progress()) )
* .borderColor( new Color(0f, 1f, 1f, (float) (1 - state.progress())) )
* .borderRadius( (int)(60 * state.progress()) )
* ))
* }</pre>
* <b>Not that the effect of this method can also be modelled using {@link #animateFor(LifeTime, Animation)}
* and {@link #style(AnimationState, Styler)} as follows:</b>
* <pre>{@code
* UI.button("Click me").withPrefSize(400, 400)
* .onMouseClick( it -> it.animateFor(2, TimeUnit.SECONDS, state -> {
* it.style(state, style -> style
* // This is the same as the animateStyleFor() method above!
* );
* }))
* }</pre>
* Also see {@link #animateStyleFor(LifeTime, AnimatedStyler)} for a version of this method which uses a {@link LifeTime} instead of a duration.
* If you are interested in doing more advanced style animations, consider taking a look at
* {@link UIForAnySwing#withTransitoryStyle(Event, LifeTime, AnimatedStyler)} to see how to do event based styling animations
* and {@link UIForAnySwing#withTransitionalStyle(Val, LifeTime, AnimatedStyler)} to see how to do 2 state switch based styling animations.
*
* @param duration The duration of the animation.
* @param unit The time unit of the duration.
* @param styler The styling animation task which should be executed on the EDT at the end of the current event cycle.
* It receives both the current animation state and the {@link swingtree.style.ComponentStyleDelegate}
* for which you can define the style properties.
*/
public final void animateStyleFor( double duration, TimeUnit unit, AnimatedStyler<C> styler ) {
Objects.requireNonNull(unit);
Objects.requireNonNull(styler);
UI.run(()->{ // This method might be called by the application thread, so we need to run on the EDT!
// We do the styling later in the paint method of a custom border implementation!
this.animateFor(duration, unit, state ->
ComponentExtension.from(_component).addAnimatedStyler(state, conf -> styler.style(state, conf))
);
});
}
/**
* A common use case is to animate the style of a component when a user event occurs.
* This method allows you to dispatch a styling animation to the EDT
* which will cause the component style to updated repeatedly until the animation expires.
* Because animation styles are applied last, it is guaranteed not to be overwritten by
* other {@link Styler} lambdas.
* Note that the provided styling will be removed automatically when the animation expires,
* so no manual cleanup is required.
* <p>
* Here is an example of how to use this method as part of a fancy styling animation:
* <pre>{@code
* UI.button("Click me").withPrefSize(400, 400)
* .onMouseClick( it -> it.animateStyleFor(UI.lifetime(2, TimeUnit.SECONDS), (state, style) ->
* .borderWidthAt(UI.Edge.BOTTOM, (int)(6 * state.progress()) )
* .borderColor( new Color(0f, 1f, 1f, (float) (1 - state.progress())) )
* .borderRadius( (int)(60 * state.progress()) )
* ))
* }</pre>
* <b>Not that the effect of this method can also be modelled using {@link #animateFor(LifeTime, Animation)}
* and {@link #style(AnimationState, Styler)} as follows:</b>
* <pre>{@code
* UI.button("Click me").withPrefSize(400, 400)
* .onMouseClick( it -> it.animateFor(UI.lifetime(2, TimeUnit.SECONDS), state -> {
* it.style(state, style -> style
* // This is the same as the animateStyleFor() method above!
* );
* }))
* }</pre>
* Also see {@link #animateStyleFor(double, TimeUnit, AnimatedStyler)} for a version of this method which uses a {@link LifeTime} instead of a duration.
* If you are interested in doing more advanced style animations, consider taking a look at
* {@link UIForAnySwing#withTransitoryStyle(Event, LifeTime, AnimatedStyler)} to see how to do event based styling animations
* and {@link UIForAnySwing#withTransitionalStyle(Val, LifeTime, AnimatedStyler)} to see how to do 2 state switch based styling animations.
*
* @param lifetime The lifetime of the animation.
* The animation will be removed automatically when the lifetime expires.
* @param styler The styling animation task which should be executed on the EDT at the end of the current event cycle.
* It receives both the current animation state and the {@link swingtree.style.ComponentStyleDelegate}
* for which you can define the style properties.
*/
public final void animateStyleFor( LifeTime lifetime, AnimatedStyler<C> styler ) {
Objects.requireNonNull(lifetime);
Objects.requireNonNull(styler);
UI.run(()->{ // This method might be called by the application thread, so we need to run on the EDT!
// We do the styling later in the paint method of a custom border implementation!
this.animateFor(lifetime, state ->
ComponentExtension.from(_component).addAnimatedStyler(state, conf -> styler.style(state, conf))
);
});
}
/**
* A common use case is to style the component based on the current animation state.
* This method allows you to dispatch a styling task to the EDT
* which will be executed before the next component repaint.
* Because animation styles are applied last, it is guaranteed not to be overwritten by
* other styles.
* The provided styling will be removed when the animation expires.
* <p>
* Here is an example of how to use this method as part of a fancy styling animation:
* <pre>{@code
* UI.button("Click me").withPrefSize(400, 400)
* .onMouseClick( it -> it.animateFor(2, TimeUnit.SECONDS, state -> {
* it.style(state, style -> style
* .borderWidth((int)(10 * state.progress()))
* .borderColor(new Color(1f, 1f, 0f, (float) (1 - state.progress())))
* .borderRadius((int)(100 * state.progress()))
* );
* }))
* }</pre>
*
* @param state The current animation state, which is important so that the styling can be synchronized with the animation.
* @param styler The styling task which should be executed on the EDT at the end of the current event cycle.
*/
public final void style( AnimationState state, Styler<C> styler ) {
Objects.requireNonNull(state);
Objects.requireNonNull(styler);
UI.run(()->{ // This method might be called by the application thread, so we need to run on the EDT!
// We do the styling later in the paint method of a custom border implementation!
ComponentExtension.from(_component).addAnimatedStyler(state, styler);
});
}
/**
* Exposes access the animation builder API, where you can define the conditions
* under which the animation should be executed and then dispatch the animation to the EDT
* through the {@link Animator#go(Animation)} method.
*
* @param duration The duration of the animation.
* @param unit The time unit of the duration.
* @return An {@link Animator} instance which can be used to define how the animation should be executed.
*/
public final Animator animateFor( double duration, TimeUnit unit ) {
Objects.requireNonNull(unit);
return Animator.animateFor(LifeTime.of(duration, unit), _component());
}
/**
* Exposes access the animation builder API, where you can define the conditions
* under which the animation should be executed and then dispatch the animation to the EDT
* through the {@link Animator#go(Animation)} method.
*
* @param lifeTime The lifetime of the animation.
* @return An {@link Animator} instance which can be used to define how the animation should be executed.
*/
public final Animator animateFor( LifeTime lifeTime ) {
Objects.requireNonNull(lifeTime);
return Animator.animateFor(lifeTime, _component());
}
/**
* Use this to schedule and run the provided animation
* to be executed on the EDT.
* A single animation iteration may be executed multiple times
* for the given duration in order to achieve a smooth transition. <br>
* Here an example of how to use this method
* on a "Save" button:
* <pre>{@code
* UI.button("Save").withPrefSize(400, 400)
* .onMouseClick( it -> it
* .animateFor(
* UI.lifetime(1, TimeUnit.SECONDS)
* .startingIn( 0.5, TimeUnit.SECONDS )
* )
* .go( myAnimation )
* )
* }</pre>
*
*
* @param lifeTime The lifetime of the animation.
* @param animation The animation that should be executed.
*/
public final void animateFor( LifeTime lifeTime, Animation animation ) {
Objects.requireNonNull(lifeTime);
Objects.requireNonNull(animation);
Animator.animateFor(lifeTime, _component()).go(animation);
}
/**
* Use this to schedule and run the provided animation
* to be executed on the EDT.
* A single animation iteration may be executed multiple times
* for the given duration in order to achieve a smooth transition.
*
* @param duration The duration of the animation.
* @param unit The time unit of the duration.
* @param animation The animation that should be executed.
*/
public final void animateFor( double duration, TimeUnit unit, Animation animation ) {
Objects.requireNonNull(unit);
Objects.requireNonNull(animation);
this.animateFor(duration, unit).go(animation);
}
/**
* The number returned by this method is used to scale the UI
* to ensure that the UI is scaled properly for high resolution displays (high dots-per-inch, or DPI).
* Use it inside custom {@link Painter} implementations (see {@link #paint(AnimationState, Painter)})
* to scale custom {@link Graphics2D} painting operations.
*
* @return The current UI scale factor, which is used to scale the UI
* for high resolution displays (high dots-per-inch, or DPI).
*/
public float getScale() { return UI.scale(); }
/**
* The number returned by this method is used to scale the UI
* to ensure that the UI is scaled properly for high resolution displays (high dots-per-inch, or DPI).
* Use it inside custom {@link Painter} implementations (see {@link #paint(AnimationState, Painter)})
* to scale custom {@link Graphics2D} painting operations.
*
* @return The current UI scale factor, which is used to scale the UI
* for high resolution displays (high dots-per-inch, or DPI).
*/
public float scale() { return UI.scale(); }
/**
* Use this method inside custom {@link Painter} implementations (see {@link #paint(AnimationState, Painter)})
* to scale an {@code int} value by the current UI scale factor to ensure
* that the UI is scaled properly for high resolution displays (high dots-per-inch, or DPI).
* @param value The {@code int} value to scale.
* @return The scaled {@code int} value.
*/
public int scale( int value ) { return UI.scale(value); }
/**
* Use this method inside custom {@link Painter} implementations (see {@link #paint(AnimationState, Painter)})
* to scale a {@code float} value by the current UI scale factor to ensure
* that the UI is scaled properly for high resolution displays (high dots-per-inch, or DPI).
* @param value The {@code float} value to scale.
* @return The scaled {@code float} value.
*/
public float scale( float value ) { return UI.scale(value); }
/**
* Use this method inside custom {@link Painter} implementations (see {@link #paint(AnimationState, Painter)})
* to scale a {@code double} value by the current UI scale factor to ensure
* that the UI is scaled properly for high resolution displays (high dots-per-inch, or DPI).
* @param value The {@code double} value to scale.
* @return The scaled {@code double} value.
*/
public double scale( double value ) { return UI.scale(value); }
}