LayerRenderConf.java

package swingtree.style;

import com.google.errorprone.annotations.Immutable;
import swingtree.UI;

import java.awt.Graphics2D;
import java.util.Objects;

/**
 *  An immutable snapshot of essential component state needed for rendering
 *  the style of a particular component layer using the {@link StyleRenderer} and its
 *  {@link StyleRenderer#renderStyleOn(UI.Layer, LayerRenderConf, Graphics2D)} ethod. <br>
 *  This (and all of its parts) is immutable to use it as a basis for caching.
 *  When the config changes compared to the previous one, the image buffer based
 *  render cache is being invalidated and the component is rendered again
 *  (potentially with a new cached image buffer).
 */
@Immutable
@SuppressWarnings("Immutable")
final class LayerRenderConf
{
    private static final LayerRenderConf _NONE = new LayerRenderConf(
                                                    BoxModelConf.none(),
                                                    BaseColorConf.none(),
                                                    StyleConfLayer.empty()
                                                );

    public static LayerRenderConf none() { return _NONE; }

    private final BoxModelConf   _boxModelConf;
    private final BaseColorConf  _baseColor;
    private final StyleConfLayer _layer;

    private boolean _wasAlreadyHashed = false;
    private int     _hashCode         = 0; // cached hash code


    private LayerRenderConf(
        BoxModelConf   boxModelConf,
        BaseColorConf  base,
        StyleConfLayer layers
    ) {
        _boxModelConf = ComponentAreas.intern(Objects.requireNonNull(boxModelConf));
        _baseColor    = Objects.requireNonNull(base);
        _layer        = Objects.requireNonNull(layers);
    }

    static LayerRenderConf of(
        BoxModelConf   boxModelConf,
        BaseColorConf  base,
        StyleConfLayer layers
    ) {
        if (
            boxModelConf .equals( BoxModelConf.none()  ) &&
            base         .equals( BaseColorConf.none() ) &&
            layers       .equals( _NONE._layer )
        )
            return _NONE;
        else
            return new LayerRenderConf(boxModelConf, base, layers);
    }

    static LayerRenderConf of( UI.Layer layer, ComponentConf fullConf ) {
        BoxModelConf boxModelConf = BoxModelConf.of(
                                        fullConf.style().border(),
                                        fullConf.areaMarginCorrection(),
                                        fullConf.currentBounds().size()
                                    );
        BaseColorConf colorConf = BaseColorConf.of(
                                    fullConf.style().base().foundationColor().filter( c -> layer == UI.Layer.BACKGROUND ).orElse(null),
                                    fullConf.style().base().backgroundColor().filter( c -> layer == UI.Layer.BACKGROUND ).orElse(null),
                                    layer == UI.Layer.BORDER ? fullConf.style().border().colors() : BorderColorsConf.none()
                                );
        return of(
                    boxModelConf,
                    colorConf,
                    fullConf.style().layer(layer)
                );
    }

    BoxModelConf boxModel() { return _boxModelConf; }

    BaseColorConf baseColors() { return _baseColor; }

    StyleConfLayer layer() { return _layer; }

    ComponentAreas areas() { return _boxModelConf.areas(); }


    @Override
    public int hashCode() {
        if ( _wasAlreadyHashed )
            return _hashCode;

        _hashCode = Objects.hash(_boxModelConf, _baseColor, _layer);
        _wasAlreadyHashed = true;
        return _hashCode;
    }

    @Override
    public boolean equals( Object o ) {
        if ( o == this ) return true;
        if ( o == null ) return false;
        if ( o.getClass() != this.getClass() ) return false;
        LayerRenderConf other = (LayerRenderConf) o;
        return Objects.equals(_boxModelConf, other._boxModelConf) &&
               Objects.equals(_baseColor, other._baseColor) &&
               Objects.equals(_layer, other._layer);
    }

    @Override
    public String toString() {
        return getClass().getSimpleName()+"[" +
                    "boxModel=" + _boxModelConf + ", " +
                    "baseColor=" + _baseColor + ", " +
                    "layer=" + _layer +
                ']';
    }


}