blob: 926d920ec7c94a26498c0da0a23170ebefc12bb2 [file] [log] [blame]
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.wear.protolayout;
import static androidx.annotation.Dimension.DP;
import static androidx.annotation.Dimension.SP;
import static androidx.wear.protolayout.expression.Preconditions.checkNotNull;
import androidx.annotation.Dimension;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.OptIn;
import androidx.annotation.RestrictTo;
import androidx.annotation.RestrictTo.Scope;
import androidx.wear.protolayout.TypeBuilders.FloatProp;
import androidx.wear.protolayout.expression.DynamicBuilders;
import androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat;
import androidx.wear.protolayout.expression.ExperimentalProtoLayoutExtensionApi;
import androidx.wear.protolayout.expression.Fingerprint;
import androidx.wear.protolayout.proto.DimensionProto;
/** Builders for dimensions for layout elements. */
public final class DimensionBuilders {
private DimensionBuilders() {}
private static final ExpandedDimensionProp EXPAND = new ExpandedDimensionProp.Builder().build();
private static final WrappedDimensionProp WRAP = new WrappedDimensionProp.Builder().build();
/**
* Shortcut for building a {@link DpProp} using a measurement in DP.
*
* @since 1.0
*/
@NonNull
public static DpProp dp(@Dimension(unit = DP) float valueDp) {
return new DpProp.Builder(valueDp).build();
}
/**
* Shortcut for building a {@link SpProp} using a measurement in SP.
*
* @since 1.0
*/
@NonNull
public static SpProp sp(@Dimension(unit = SP) float valueSp) {
return new SpProp.Builder().setValue(valueSp).build();
}
/**
* Shortcut for building a {@link EmProp} using a measurement in EM.
*
* @since 1.0
*/
@NonNull
public static EmProp em(int valueEm) {
return new EmProp.Builder().setValue(valueEm).build();
}
/**
* Shortcut for building a {@link EmProp} using a measurement in EM.
*
* @since 1.0
*/
@NonNull
public static EmProp em(float valueEm) {
return new EmProp.Builder().setValue(valueEm).build();
}
/**
* Shortcut for building an {@link DegreesProp} using a measurement in degrees.
*
* @since 1.0
*/
@NonNull
public static DegreesProp degrees(float valueDegrees) {
return new DegreesProp.Builder(valueDegrees).build();
}
/**
* Shortcut for building an {@link ExpandedDimensionProp} that will expand to the size of its
* parent.
*
* @since 1.0
*/
@NonNull
public static ExpandedDimensionProp expand() {
return EXPAND;
}
/**
* Shortcut for building an {@link WrappedDimensionProp} that will shrink to the size of its
* children.
*
* @since 1.0
*/
@NonNull
public static WrappedDimensionProp wrap() {
return WRAP;
}
/**
* A type for linear dimensions, measured in dp.
*
* @since 1.0
*/
@OptIn(markerClass = ExperimentalProtoLayoutExtensionApi.class)
public static final class DpProp
implements ContainerDimension, ImageDimension, SpacerDimension, ExtensionDimension {
private final DimensionProto.DpProp mImpl;
@Nullable private final Fingerprint mFingerprint;
DpProp(DimensionProto.DpProp impl, @Nullable Fingerprint fingerprint) {
this.mImpl = impl;
this.mFingerprint = fingerprint;
}
/**
* Gets the static value, in dp. If a dynamic value is also set and the renderer supports
* dynamic values for the corresponding field, this static value will be ignored. If the
* static value is not specified, zero will be used instead.
*
* @since 1.0
*/
@Dimension(unit = DP)
public float getValue() {
return mImpl.getValue();
}
/**
* Gets the dynamic value, in dp. Note that when setting this value, the static value is
* still required to be set to support older renderers that only read the static value. If
* {@code dynamicValue} has an invalid result, the provided static value will be used
* instead.
*
* @since 1.2
*/
@Nullable
public DynamicFloat getDynamicValue() {
if (mImpl.hasDynamicValue()) {
return DynamicBuilders.dynamicFloatFromProto(mImpl.getDynamicValue());
} else {
return null;
}
}
@Override
@RestrictTo(Scope.LIBRARY_GROUP)
@Nullable
public Fingerprint getFingerprint() {
return mFingerprint;
}
/** Creates a new wrapper instance from the proto. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public static DpProp fromProto(
@NonNull DimensionProto.DpProp proto, @Nullable Fingerprint fingerprint) {
return new DpProp(proto, fingerprint);
}
@NonNull
static DpProp fromProto(@NonNull DimensionProto.DpProp proto) {
return fromProto(proto, null);
}
/** Returns the internal proto instance. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
DimensionProto.DpProp toProto() {
return mImpl;
}
@Override
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public DimensionProto.ContainerDimension toContainerDimensionProto() {
return DimensionProto.ContainerDimension.newBuilder().setLinearDimension(mImpl).build();
}
@Override
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public DimensionProto.ImageDimension toImageDimensionProto() {
return DimensionProto.ImageDimension.newBuilder().setLinearDimension(mImpl).build();
}
@Override
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public DimensionProto.SpacerDimension toSpacerDimensionProto() {
return DimensionProto.SpacerDimension.newBuilder().setLinearDimension(mImpl).build();
}
@Override
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
@ExperimentalProtoLayoutExtensionApi
public DimensionProto.ExtensionDimension toExtensionDimensionProto() {
return DimensionProto.ExtensionDimension.newBuilder().setLinearDimension(mImpl).build();
}
@Override
@NonNull
public String toString() {
return "DpProp{" + "value=" + getValue() + ", dynamicValue=" + getDynamicValue() + "}";
}
/** Builder for {@link DpProp}. */
public static final class Builder
implements ContainerDimension.Builder,
ImageDimension.Builder,
SpacerDimension.Builder,
ExtensionDimension.Builder {
private final DimensionProto.DpProp.Builder mImpl = DimensionProto.DpProp.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(756413087);
/**
* Creates an instance of {@link Builder} from the given static value. {@link
* #setDynamicValue(DynamicFloat)} can be used to provide a dynamic value.
*/
public Builder(@Dimension(unit = DP) float staticValue) {
setValue(staticValue);
}
/**
* Creates an instance of {@link Builder}.
*
* @deprecated use {@link #Builder(float)}
*/
@Deprecated
public Builder() {}
/**
* Sets the static value, in dp. If a dynamic value is also set and the renderer
* supports dynamic values for the corresponding field, this static value will be
* ignored. If the static value is not specified, zero will be used instead.
*
* @since 1.0
*/
@NonNull
public Builder setValue(@Dimension(unit = DP) float value) {
mImpl.setValue(value);
mFingerprint.recordPropertyUpdate(1, Float.floatToIntBits(value));
return this;
}
/**
* Sets the dynamic value, in dp. Note that when setting this value, the static value is
* still required to be set to support older renderers that only read the static value.
* If {@code dynamicValue} has an invalid result, the provided static value will be used
* instead.
*
* @since 1.2
*/
@NonNull
public Builder setDynamicValue(@NonNull DynamicFloat dynamicValue) {
mImpl.setDynamicValue(dynamicValue.toDynamicFloatProto());
mFingerprint.recordPropertyUpdate(
2, checkNotNull(dynamicValue.getFingerprint()).aggregateValueAsInt());
return this;
}
/**
* Builds an instance from accumulated values.
*
* @throws IllegalStateException if a dynamic value is set using {@link
* #setDynamicValue(DynamicFloat)} but neither {@link #Builder(float)} nor {@link
* #setValue(float)} is used to provide a static value.
*/
@Override
@NonNull
public DpProp build() {
if (mImpl.hasDynamicValue() && !mImpl.hasValue()) {
throw new IllegalStateException("Static value is missing.");
}
return new DpProp(mImpl.build(), mFingerprint);
}
}
}
private static class DpPropLayoutConstraint {
protected final DimensionProto.DpProp mImpl;
@Nullable protected final Fingerprint mFingerprint;
protected DpPropLayoutConstraint(
DimensionProto.DpProp impl, @Nullable Fingerprint fingerprint) {
this.mImpl = impl;
this.mFingerprint = fingerprint;
}
/**
* Gets the value to use when laying out components which can have a dynamic value.
* Constrains the layout so that components are not changing size or location regardless of
* the dynamic value that is being provided.
*
* @since 1.2
*/
@SuppressWarnings("Unused")
@Dimension(unit = DP)
public float getValue() {
return mImpl.getValueForLayout();
}
@SuppressWarnings("Unused")
@RestrictTo(Scope.LIBRARY_GROUP)
@Nullable
public Fingerprint getFingerprint() {
return mFingerprint;
}
@SuppressWarnings("Unused")
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public DimensionProto.SpacerDimension toSpacerDimensionProto() {
return DimensionProto.SpacerDimension.newBuilder().setLinearDimension(mImpl).build();
}
/** Builder for {@link DpPropLayoutConstraint}. */
protected static class Builder {
protected final DimensionProto.DpProp.Builder mImpl =
DimensionProto.DpProp.newBuilder();
protected final Fingerprint mFingerprint = new Fingerprint(756413088);
/**
* Creates a new builder for {@link DpPropLayoutConstraint}.
*
* @param value Sets the value to use when laying out components which can have a
* dynamic value. Constrains the layout so that components are not changing size or
* location regardless of the dynamic value that is being provided.
* @since 1.2
*/
protected Builder(@Dimension(unit = DP) float value) {
setValue(value);
}
/**
* Sets the value to use when laying out components which can have a dynamic value.
* Constrains the layout so that components are not changing size or location regardless
* of the dynamic value that is being provided.
*
* @since 1.2
*/
@NonNull
private Builder setValue(@Dimension(unit = DP) float value) {
mImpl.setValueForLayout(value);
mFingerprint.recordPropertyUpdate(3, Float.floatToIntBits(value));
return this;
}
}
}
/**
* A type for specifying horizontal layout constraints when using {@link DpProp} on a data
* bindable layout element.
*
* @since 1.2
*/
public static final class HorizontalLayoutConstraint extends DpPropLayoutConstraint {
HorizontalLayoutConstraint(DimensionProto.DpProp impl, @Nullable Fingerprint fingerprint) {
super(impl, fingerprint);
}
/**
* Gets the horizontal alignment of the actual content within the space reserved by value.
*
* @since 1.2
*/
@LayoutElementBuilders.HorizontalAlignment
public int getHorizontalAlignment() {
return mImpl.getHorizontalAlignmentForLayoutValue();
}
@NonNull
static HorizontalLayoutConstraint fromProto(@NonNull DimensionProto.DpProp proto) {
return new HorizontalLayoutConstraint(proto, null);
}
/** Builder for {@link HorizontalLayoutConstraint}. */
public static final class Builder extends DpPropLayoutConstraint.Builder {
/**
* Creates a new builder for {@link HorizontalLayoutConstraint}.
*
* @param value Sets the value to use when laying out components which can have a
* dynamic value. Constrains the layout so that components are not changing size or
* location regardless of the dynamic value that is being provided.
* @since 1.2
*/
public Builder(@Dimension(unit = DP) float value) {
super(value);
}
/**
* Sets the horizontal alignment of the actual content within the space reserved by
* value. If not specified, defaults to center alignment.
*
* @since 1.2
*/
@NonNull
public Builder setHorizontalAlignment(
@LayoutElementBuilders.HorizontalAlignment int horizontalAlignment) {
mImpl.setHorizontalAlignmentForLayoutValue(horizontalAlignment);
mFingerprint.recordPropertyUpdate(5, horizontalAlignment);
return this;
}
/** Builds an instance of {@link HorizontalLayoutConstraint}. */
@NonNull
public HorizontalLayoutConstraint build() {
return new HorizontalLayoutConstraint(mImpl.build(), mFingerprint);
}
}
}
/**
* A type for specifying vertical layout constraints when using {@link DpProp} on a data
* bindable layout element.
*
* @since 1.2
*/
public static final class VerticalLayoutConstraint extends DpPropLayoutConstraint {
VerticalLayoutConstraint(DimensionProto.DpProp impl, @Nullable Fingerprint fingerprint) {
super(impl, fingerprint);
}
/**
* Gets the vertical alignment of the actual content within the space reserved by value.
*
* @since 1.2
*/
@LayoutElementBuilders.VerticalAlignment
public int getVerticalAlignment() {
return mImpl.getVerticalAlignmentForLayoutValue();
}
@NonNull
static VerticalLayoutConstraint fromProto(@NonNull DimensionProto.DpProp proto) {
return new VerticalLayoutConstraint(proto, null);
}
/** Builder for {@link VerticalLayoutConstraint}. */
public static final class Builder extends DpPropLayoutConstraint.Builder {
/**
* Creates a new builder for {@link VerticalLayoutConstraint}.
*
* @param value Sets the value to use when laying out components which can have a
* dynamic value. Constrains the layout so that components are not changing size or
* location regardless of the dynamic value that is being provided.
* @since 1.2
*/
public Builder(@Dimension(unit = DP) float value) {
super(value);
}
/**
* Sets the vertical alignment of the actual content within the space reserved by value.
* If not specified, defaults to center alignment.
*
* @since 1.2
*/
@NonNull
public Builder setVerticalAlignment(
@LayoutElementBuilders.VerticalAlignment int verticalAlignment) {
mImpl.setVerticalAlignmentForLayoutValue(verticalAlignment);
mFingerprint.recordPropertyUpdate(4, verticalAlignment);
return this;
}
/** Builds an instance of {@link VerticalLayoutConstraint}. */
@NonNull
public VerticalLayoutConstraint build() {
return new VerticalLayoutConstraint(mImpl.build(), mFingerprint);
}
}
}
/**
* A type for font sizes, measured in sp.
*
* @since 1.0
*/
public static final class SpProp {
private final DimensionProto.SpProp mImpl;
@Nullable private final Fingerprint mFingerprint;
SpProp(DimensionProto.SpProp impl, @Nullable Fingerprint fingerprint) {
this.mImpl = impl;
this.mFingerprint = fingerprint;
}
/**
* Gets the value, in sp.
*
* @since 1.0
*/
@Dimension(unit = SP)
public float getValue() {
return mImpl.getValue();
}
/** Get the fingerprint for this object, or null if unknown. */
@RestrictTo(Scope.LIBRARY_GROUP)
@Nullable
public Fingerprint getFingerprint() {
return mFingerprint;
}
/** Creates a new wrapper instance from the proto. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public static SpProp fromProto(
@NonNull DimensionProto.SpProp proto, @Nullable Fingerprint fingerprint) {
return new SpProp(proto, fingerprint);
}
@NonNull
static SpProp fromProto(@NonNull DimensionProto.SpProp proto) {
return fromProto(proto, null);
}
/** Returns the internal proto instance. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public DimensionProto.SpProp toProto() {
return mImpl;
}
@Override
@NonNull
public String toString() {
return "SpProp{" + "value=" + getValue() + "}";
}
/** Builder for {@link SpProp} */
public static final class Builder {
private final DimensionProto.SpProp.Builder mImpl = DimensionProto.SpProp.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(631793260);
/** Creates an instance of {@link Builder}. */
public Builder() {}
/**
* Sets the value, in sp.
*
* @since 1.0
*/
@NonNull
public Builder setValue(@Dimension(unit = SP) float value) {
mImpl.setValue(value);
mFingerprint.recordPropertyUpdate(2, Float.floatToIntBits(value));
return this;
}
/** Builds an instance from accumulated values. */
@NonNull
public SpProp build() {
return new SpProp(mImpl.build(), mFingerprint);
}
}
}
/**
* A type for font spacing, measured in em.
*
* @since 1.0
*/
public static final class EmProp {
private final DimensionProto.EmProp mImpl;
@Nullable private final Fingerprint mFingerprint;
EmProp(DimensionProto.EmProp impl, @Nullable Fingerprint fingerprint) {
this.mImpl = impl;
this.mFingerprint = fingerprint;
}
/**
* Gets the value, in em.
*
* @since 1.0
*/
public float getValue() {
return mImpl.getValue();
}
/** Get the fingerprint for this object, or null if unknown. */
@RestrictTo(Scope.LIBRARY_GROUP)
@Nullable
public Fingerprint getFingerprint() {
return mFingerprint;
}
/** Creates a new wrapper instance from the proto. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public static EmProp fromProto(
@NonNull DimensionProto.EmProp proto, @Nullable Fingerprint fingerprint) {
return new EmProp(proto, fingerprint);
}
@NonNull
static EmProp fromProto(@NonNull DimensionProto.EmProp proto) {
return fromProto(proto, null);
}
/** Returns the internal proto instance. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public DimensionProto.EmProp toProto() {
return mImpl;
}
@Override
@NonNull
public String toString() {
return "EmProp{" + "value=" + getValue() + "}";
}
/** Builder for {@link EmProp} */
public static final class Builder {
private final DimensionProto.EmProp.Builder mImpl = DimensionProto.EmProp.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(-659639046);
/** Creates an instance of {@link Builder}. */
public Builder() {}
/**
* Sets the value, in em.
*
* @since 1.0
*/
@NonNull
public Builder setValue(float value) {
mImpl.setValue(value);
mFingerprint.recordPropertyUpdate(1, Float.floatToIntBits(value));
return this;
}
/** Builds an instance from accumulated values. */
@NonNull
public EmProp build() {
return new EmProp(mImpl.build(), mFingerprint);
}
}
}
/**
* A type for angular dimensions, measured in degrees.
*
* @since 1.0
*/
public static final class DegreesProp {
private final DimensionProto.DegreesProp mImpl;
@Nullable private final Fingerprint mFingerprint;
DegreesProp(DimensionProto.DegreesProp impl, @Nullable Fingerprint fingerprint) {
this.mImpl = impl;
this.mFingerprint = fingerprint;
}
/**
* Gets the static value, in degrees. If a dynamic value is also set and the renderer
* supports dynamic values for the corresponding field, this static value will be ignored.
* If the static value is not specified, zero will be used instead.
*
* @since 1.0
*/
public float getValue() {
return mImpl.getValue();
}
/**
* Gets the dynamic value, in degrees. Note that when setting this value, the static value
* is still required to be set to support older renderers that only read the static value.
* If {@code dynamicValue} has an invalid result, the provided static value will be used
* instead.
*
* @since 1.2
*/
@Nullable
public DynamicFloat getDynamicValue() {
if (mImpl.hasDynamicValue()) {
return DynamicBuilders.dynamicFloatFromProto(mImpl.getDynamicValue());
} else {
return null;
}
}
/** Get the fingerprint for this object, or null if unknown. */
@RestrictTo(Scope.LIBRARY_GROUP)
@Nullable
public Fingerprint getFingerprint() {
return mFingerprint;
}
/** Creates a new wrapper instance from the proto. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public static DegreesProp fromProto(
@NonNull DimensionProto.DegreesProp proto, @Nullable Fingerprint fingerprint) {
return new DegreesProp(proto, fingerprint);
}
@NonNull
static DegreesProp fromProto(@NonNull DimensionProto.DegreesProp proto) {
return fromProto(proto, null);
}
/** Returns the internal proto instance. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public DimensionProto.DegreesProp toProto() {
return mImpl;
}
@Override
@NonNull
public String toString() {
return "DegreesProp{"
+ "value="
+ getValue()
+ ", dynamicValue="
+ getDynamicValue()
+ "}";
}
/** Builder for {@link DegreesProp} */
public static final class Builder {
private final DimensionProto.DegreesProp.Builder mImpl =
DimensionProto.DegreesProp.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(-1927567665);
/**
* Creates an instance of {@link Builder} from the given static value. {@link
* #setDynamicValue(DynamicFloat)} can be used to provide a dynamic value.
*/
public Builder(float staticValue) {
setValue(staticValue);
}
/**
* Creates an instance of {@link Builder}.
*
* @deprecated use {@link #Builder(float)}
*/
@Deprecated
public Builder() {}
/**
* Sets the static value, in degrees. If a dynamic value is also set and the renderer
* supports dynamic values for the corresponding field, this static value will be
* ignored. If the static value is not specified, zero will be used instead.
*
* @since 1.0
*/
@NonNull
public Builder setValue(float value) {
mImpl.setValue(value);
mFingerprint.recordPropertyUpdate(1, Float.floatToIntBits(value));
return this;
}
/**
* Sets the dynamic value, in degrees. Note that when setting this value, the static
* value is still required to be set to support older renderers that only read the
* static value. If {@code dynamicValue} has an invalid result, the provided static
* value will be used instead.
*
* @since 1.2
*/
@NonNull
public Builder setDynamicValue(@NonNull DynamicFloat dynamicValue) {
mImpl.setDynamicValue(dynamicValue.toDynamicFloatProto());
mFingerprint.recordPropertyUpdate(
2, checkNotNull(dynamicValue.getFingerprint()).aggregateValueAsInt());
return this;
}
/**
* Builds an instance from accumulated values.
*
* @throws IllegalStateException if a dynamic value is set using {@link
* #setDynamicValue(DynamicFloat)} but neither {@link #Builder(float)} nor {@link
* #setValue(float)} is used to provide a static value.
*/
@NonNull
public DegreesProp build() {
if (mImpl.hasDynamicValue() && !mImpl.hasValue()) {
throw new IllegalStateException("Static value is missing.");
}
return new DegreesProp(mImpl.build(), mFingerprint);
}
}
}
/**
* A type for specifying layout constraints when using {@link DegreesProp} on a data bindable
* layout element.
*
* @since 1.2
*/
public static final class AngularLayoutConstraint {
private final DimensionProto.DegreesProp mImpl;
@Nullable private final Fingerprint mFingerprint;
AngularLayoutConstraint(
DimensionProto.DegreesProp impl, @Nullable Fingerprint fingerprint) {
this.mImpl = impl;
this.mFingerprint = fingerprint;
}
/**
* Gets the fixed value to reserve the space when used on a layout-changing data bind. If
* not set defaults to the static value of the associated {@link DegreesProp} field.
*
* @since 1.2
*/
@Dimension(unit = DP)
public float getValue() {
return mImpl.getValueForLayout();
}
/**
* Gets angular alignment of the actual content within the space reserved by value.
*
* @since 1.2
*/
@LayoutElementBuilders.AngularAlignment
public int getAngularAlignment() {
return mImpl.getAngularAlignmentForLayoutValue();
}
@RestrictTo(Scope.LIBRARY_GROUP)
@Nullable
public Fingerprint getFingerprint() {
return mFingerprint;
}
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public DimensionProto.DegreesProp toProto() {
return mImpl;
}
@NonNull
static AngularLayoutConstraint fromProto(@NonNull DimensionProto.DegreesProp proto) {
return new AngularLayoutConstraint(proto, null);
}
/** Builder for {@link AngularLayoutConstraint}. */
public static final class Builder {
private final DimensionProto.DegreesProp.Builder mImpl =
DimensionProto.DegreesProp.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(-1927567664);
/**
* Creates a new builder for {@link AngularLayoutConstraint}.
*
* @param value Sets the fixed value to reserve the space when used on a layout-changing
* data bind.
* @since 1.2
*/
public Builder(@Dimension(unit = DP) float value) {
setValue(value);
}
/**
* Sets the fixed value to reserve the space when used on a layout-changing data bind.
*
* @since 1.2
*/
@NonNull
private Builder setValue(@Dimension(unit = DP) float value) {
mImpl.setValueForLayout(value);
mFingerprint.recordPropertyUpdate(3, Float.floatToIntBits(value));
return this;
}
/**
* Sets angular alignment of the actual content within the space reserved by value. If
* not specified, defaults to center alignment.
*
* @since 1.2
*/
@NonNull
public Builder setAngularAlignment(
@LayoutElementBuilders.AngularAlignment int angularAlignment) {
mImpl.setAngularAlignmentForLayoutValue(angularAlignment);
mFingerprint.recordPropertyUpdate(4, angularAlignment);
return this;
}
/** Builds an instance of {@link AngularLayoutConstraint}. */
@NonNull
public AngularLayoutConstraint build() {
return new AngularLayoutConstraint(mImpl.build(), mFingerprint);
}
}
}
/**
* A type for a dimension that fills all the space it can (i.e. MATCH_PARENT in Android
* parlance).
*
* @since 1.0
*/
public static final class ExpandedDimensionProp implements ContainerDimension, ImageDimension {
private final DimensionProto.ExpandedDimensionProp mImpl;
@Nullable private final Fingerprint mFingerprint;
ExpandedDimensionProp(
DimensionProto.ExpandedDimensionProp impl, @Nullable Fingerprint fingerprint) {
this.mImpl = impl;
this.mFingerprint = fingerprint;
}
/**
* Gets the layout weight (a dimensionless scalar value) for this element. This will only
* affect the width of children of a {@link
* androidx.wear.protolayout.LayoutElementBuilders.Row} or the height of children of a
* {@link androidx.wear.protolayout.LayoutElementBuilders.Column}. By default, all children
* have equal weight. Where applicable, the width or height of the element is proportional
* to the sum of the weights of its siblings.
*
* @since 1.2
*/
@Nullable
public FloatProp getLayoutWeight() {
if (mImpl.hasLayoutWeight()) {
return FloatProp.fromProto(mImpl.getLayoutWeight());
} else {
return null;
}
}
@Override
@RestrictTo(Scope.LIBRARY_GROUP)
@Nullable
public Fingerprint getFingerprint() {
return mFingerprint;
}
/** Creates a new wrapper instance from the proto. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public static ExpandedDimensionProp fromProto(
@NonNull DimensionProto.ExpandedDimensionProp proto,
@Nullable Fingerprint fingerprint) {
return new ExpandedDimensionProp(proto, fingerprint);
}
@NonNull
static ExpandedDimensionProp fromProto(
@NonNull DimensionProto.ExpandedDimensionProp proto) {
return fromProto(proto, null);
}
/** Returns the internal proto instance. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
DimensionProto.ExpandedDimensionProp toProto() {
return mImpl;
}
@Override
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public DimensionProto.ContainerDimension toContainerDimensionProto() {
return DimensionProto.ContainerDimension.newBuilder()
.setExpandedDimension(mImpl)
.build();
}
@Override
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public DimensionProto.ImageDimension toImageDimensionProto() {
return DimensionProto.ImageDimension.newBuilder().setExpandedDimension(mImpl).build();
}
@Override
@NonNull
public String toString() {
return "ExpandedDimensionProp{" + "layoutWeight=" + getLayoutWeight() + "}";
}
/** Builder for {@link ExpandedDimensionProp}. */
public static final class Builder
implements ContainerDimension.Builder, ImageDimension.Builder {
private final DimensionProto.ExpandedDimensionProp.Builder mImpl =
DimensionProto.ExpandedDimensionProp.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(-997720604);
/** Creates an instance of {@link Builder}. */
public Builder() {}
/**
* Sets the layout weight (a dimensionless scalar value) for this element. This will
* only affect the width of children of a {@link
* androidx.wear.protolayout.LayoutElementBuilders.Row} or the height of children of a
* {@link androidx.wear.protolayout.LayoutElementBuilders.Column}. By default, all
* children have equal weight. Where applicable, the width or height of the element is
* proportional to the sum of the weights of its siblings.
*
* <p>Note that this field only supports static values.
*
* @since 1.2
*/
@NonNull
public Builder setLayoutWeight(@NonNull FloatProp layoutWeight) {
if (layoutWeight.getDynamicValue() != null) {
throw new IllegalArgumentException(
"setLayoutWeight doesn't support dynamic values.");
}
mImpl.setLayoutWeight(layoutWeight.toProto());
mFingerprint.recordPropertyUpdate(
1, checkNotNull(layoutWeight.getFingerprint()).aggregateValueAsInt());
return this;
}
/** Builds an instance from accumulated values. */
@Override
@NonNull
public ExpandedDimensionProp build() {
return new ExpandedDimensionProp(mImpl.build(), mFingerprint);
}
}
}
/**
* A type for a dimension that sizes itself to the size of its children (i.e. WRAP_CONTENT in
* Android parlance).
*
* @since 1.0
*/
public static final class WrappedDimensionProp implements ContainerDimension {
private final DimensionProto.WrappedDimensionProp mImpl;
@Nullable private final Fingerprint mFingerprint;
WrappedDimensionProp(
DimensionProto.WrappedDimensionProp impl, @Nullable Fingerprint fingerprint) {
this.mImpl = impl;
this.mFingerprint = fingerprint;
}
/**
* Gets the minimum size of this dimension. If not set, then there is no minimum size.
*
* @since 1.2
*/
@Nullable
public DpProp getMinimumSize() {
if (mImpl.hasMinimumSize()) {
return DpProp.fromProto(mImpl.getMinimumSize());
} else {
return null;
}
}
@Override
@RestrictTo(Scope.LIBRARY_GROUP)
@Nullable
public Fingerprint getFingerprint() {
return mFingerprint;
}
/** Creates a new wrapper instance from the proto. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public static WrappedDimensionProp fromProto(
@NonNull DimensionProto.WrappedDimensionProp proto,
@Nullable Fingerprint fingerprint) {
return new WrappedDimensionProp(proto, fingerprint);
}
@NonNull
static WrappedDimensionProp fromProto(@NonNull DimensionProto.WrappedDimensionProp proto) {
return fromProto(proto, null);
}
/** Returns the internal proto instance. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
DimensionProto.WrappedDimensionProp toProto() {
return mImpl;
}
@Override
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public DimensionProto.ContainerDimension toContainerDimensionProto() {
return DimensionProto.ContainerDimension.newBuilder()
.setWrappedDimension(mImpl)
.build();
}
@Override
@NonNull
public String toString() {
return "WrappedDimensionProp{" + "minimumSize=" + getMinimumSize() + "}";
}
/** Builder for {@link WrappedDimensionProp}. */
public static final class Builder implements ContainerDimension.Builder {
private final DimensionProto.WrappedDimensionProp.Builder mImpl =
DimensionProto.WrappedDimensionProp.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(1118918114);
/** Creates an instance of {@link Builder}. */
public Builder() {}
/**
* Sets the minimum size of this dimension. If not set, then there is no minimum size.
*
* <p>Note that this field only supports static values.
*
* @since 1.2
*/
@NonNull
public Builder setMinimumSize(@NonNull DpProp minimumSize) {
if (minimumSize.getDynamicValue() != null) {
throw new IllegalArgumentException(
"setMinimumSize doesn't support dynamic values.");
}
mImpl.setMinimumSize(minimumSize.toProto());
mFingerprint.recordPropertyUpdate(
1, checkNotNull(minimumSize.getFingerprint()).aggregateValueAsInt());
return this;
}
/** Builds an instance from accumulated values. */
@Override
@NonNull
public WrappedDimensionProp build() {
return new WrappedDimensionProp(mImpl.build(), mFingerprint);
}
}
}
/**
* A type for a dimension that scales itself proportionally to another dimension such that the
* aspect ratio defined by the given width and height values is preserved.
*
* <p>Note that the width and height are unitless; only their ratio is relevant. This allows for
* specifying an element's size using common ratios (e.g. width=4, height=3), or to allow an
* element to be resized proportionally based on the size of an underlying asset (e.g. an
* 800x600 image being added to a smaller container and resized accordingly).
*
* @since 1.0
*/
public static final class ProportionalDimensionProp implements ImageDimension {
private final DimensionProto.ProportionalDimensionProp mImpl;
@Nullable private final Fingerprint mFingerprint;
ProportionalDimensionProp(
DimensionProto.ProportionalDimensionProp impl, @Nullable Fingerprint fingerprint) {
this.mImpl = impl;
this.mFingerprint = fingerprint;
}
/**
* Gets the width to be used when calculating the aspect ratio to preserve.
*
* @since 1.0
*/
@IntRange(from = 0)
public int getAspectRatioWidth() {
return mImpl.getAspectRatioWidth();
}
/**
* Gets the height to be used when calculating the aspect ratio ratio to preserve.
*
* @since 1.0
*/
@IntRange(from = 0)
public int getAspectRatioHeight() {
return mImpl.getAspectRatioHeight();
}
@Override
@RestrictTo(Scope.LIBRARY_GROUP)
@Nullable
public Fingerprint getFingerprint() {
return mFingerprint;
}
/** Creates a new wrapper instance from the proto. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public static ProportionalDimensionProp fromProto(
@NonNull DimensionProto.ProportionalDimensionProp proto,
@Nullable Fingerprint fingerprint) {
return new ProportionalDimensionProp(proto, fingerprint);
}
@NonNull
static ProportionalDimensionProp fromProto(
@NonNull DimensionProto.ProportionalDimensionProp proto) {
return fromProto(proto, null);
}
/** Returns the internal proto instance. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
DimensionProto.ProportionalDimensionProp toProto() {
return mImpl;
}
@Override
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public DimensionProto.ImageDimension toImageDimensionProto() {
return DimensionProto.ImageDimension.newBuilder()
.setProportionalDimension(mImpl)
.build();
}
@Override
@NonNull
public String toString() {
return "ProportionalDimensionProp{"
+ "aspectRatioWidth="
+ getAspectRatioWidth()
+ ", aspectRatioHeight="
+ getAspectRatioHeight()
+ "}";
}
/** Builder for {@link ProportionalDimensionProp}. */
public static final class Builder implements ImageDimension.Builder {
private final DimensionProto.ProportionalDimensionProp.Builder mImpl =
DimensionProto.ProportionalDimensionProp.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(1725027476);
/** Creates an instance of {@link Builder}. */
public Builder() {}
/**
* Sets the width to be used when calculating the aspect ratio to preserve.
*
* @since 1.0
*/
@NonNull
public Builder setAspectRatioWidth(@IntRange(from = 0) int aspectRatioWidth) {
mImpl.setAspectRatioWidth(aspectRatioWidth);
mFingerprint.recordPropertyUpdate(1, aspectRatioWidth);
return this;
}
/**
* Sets the height to be used when calculating the aspect ratio ratio to preserve.
*
* @since 1.0
*/
@NonNull
public Builder setAspectRatioHeight(@IntRange(from = 0) int aspectRatioHeight) {
mImpl.setAspectRatioHeight(aspectRatioHeight);
mFingerprint.recordPropertyUpdate(2, aspectRatioHeight);
return this;
}
/** Builds an instance from accumulated values. */
@Override
@NonNull
public ProportionalDimensionProp build() {
return new ProportionalDimensionProp(mImpl.build(), mFingerprint);
}
}
}
/**
* Interface defining a dimension that can be applied to a container.
*
* @since 1.0
*/
public interface ContainerDimension {
/** Get the protocol buffer representation of this object. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
DimensionProto.ContainerDimension toContainerDimensionProto();
/** Get the fingerprint for this object or null if unknown. */
@RestrictTo(Scope.LIBRARY_GROUP)
@Nullable
Fingerprint getFingerprint();
/** Builder to create {@link ContainerDimension} objects. */
@RestrictTo(Scope.LIBRARY_GROUP)
interface Builder {
/** Builds an instance with values accumulated in this Builder. */
@NonNull
ContainerDimension build();
}
}
/** Creates a new wrapper instance from the proto. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public static ContainerDimension containerDimensionFromProto(
@NonNull DimensionProto.ContainerDimension proto, @Nullable Fingerprint fingerprint) {
if (proto.hasLinearDimension()) {
return DpProp.fromProto(proto.getLinearDimension(), fingerprint);
}
if (proto.hasExpandedDimension()) {
return ExpandedDimensionProp.fromProto(proto.getExpandedDimension(), fingerprint);
}
if (proto.hasWrappedDimension()) {
return WrappedDimensionProp.fromProto(proto.getWrappedDimension(), fingerprint);
}
throw new IllegalStateException(
"Proto was not a recognised instance of ContainerDimension");
}
@NonNull
static ContainerDimension containerDimensionFromProto(
@NonNull DimensionProto.ContainerDimension proto) {
return containerDimensionFromProto(proto, null);
}
/**
* Interface defining a dimension that can be applied to an image.
*
* @since 1.0
*/
public interface ImageDimension {
/** Get the protocol buffer representation of this object. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
DimensionProto.ImageDimension toImageDimensionProto();
/** Get the fingerprint for this object or null if unknown. */
@RestrictTo(Scope.LIBRARY_GROUP)
@Nullable
Fingerprint getFingerprint();
/** Builder to create {@link ImageDimension} objects. */
@RestrictTo(Scope.LIBRARY_GROUP)
interface Builder {
/** Builds an instance with values accumulated in this Builder. */
@NonNull
ImageDimension build();
}
}
/** Creates a new wrapper instance from the proto. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public static ImageDimension imageDimensionFromProto(
@NonNull DimensionProto.ImageDimension proto, @Nullable Fingerprint fingerprint) {
if (proto.hasLinearDimension()) {
return DpProp.fromProto(proto.getLinearDimension(), fingerprint);
}
if (proto.hasExpandedDimension()) {
return ExpandedDimensionProp.fromProto(proto.getExpandedDimension(), fingerprint);
}
if (proto.hasProportionalDimension()) {
return ProportionalDimensionProp.fromProto(
proto.getProportionalDimension(), fingerprint);
}
throw new IllegalStateException("Proto was not a recognised instance of ImageDimension");
}
@NonNull
static ImageDimension imageDimensionFromProto(@NonNull DimensionProto.ImageDimension proto) {
return imageDimensionFromProto(proto, null);
}
/**
* Interface defining a dimension that can be applied to a spacer.
*
* @since 1.0
*/
public interface SpacerDimension {
/** Get the protocol buffer representation of this object. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
DimensionProto.SpacerDimension toSpacerDimensionProto();
/** Get the fingerprint for this object or null if unknown. */
@RestrictTo(Scope.LIBRARY_GROUP)
@Nullable
Fingerprint getFingerprint();
/** Builder to create {@link SpacerDimension} objects. */
@RestrictTo(Scope.LIBRARY_GROUP)
interface Builder {
/** Builds an instance with values accumulated in this Builder. */
@NonNull
SpacerDimension build();
}
}
/** Creates a new wrapper instance from the proto. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public static SpacerDimension spacerDimensionFromProto(
@NonNull DimensionProto.SpacerDimension proto, @Nullable Fingerprint fingerprint) {
if (proto.hasLinearDimension()) {
return DpProp.fromProto(proto.getLinearDimension(), fingerprint);
}
throw new IllegalStateException("Proto was not a recognised instance of SpacerDimension");
}
@NonNull
static SpacerDimension spacerDimensionFromProto(@NonNull DimensionProto.SpacerDimension proto) {
return spacerDimensionFromProto(proto, null);
}
/**
* Interface defining a dimension that can be applied to a {@link
* androidx.wear.protolayout.LayoutElementBuilders.ExtensionLayoutElement} element.
*
* @since 1.0
*/
@ExperimentalProtoLayoutExtensionApi
public interface ExtensionDimension {
/** Get the protocol buffer representation of this object. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
DimensionProto.ExtensionDimension toExtensionDimensionProto();
/** Get the fingerprint for this object or null if unknown. */
@RestrictTo(Scope.LIBRARY_GROUP)
@Nullable
Fingerprint getFingerprint();
/** Builder to create {@link ExtensionDimension} objects. */
@RestrictTo(Scope.LIBRARY_GROUP)
interface Builder {
/** Builds an instance with values accumulated in this Builder. */
@NonNull
ExtensionDimension build();
}
}
/** Creates a new wrapper instance from the proto. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public static ExtensionDimension extensionDimensionFromProto(
@NonNull DimensionProto.ExtensionDimension proto, @Nullable Fingerprint fingerprint) {
if (proto.hasLinearDimension()) {
return DpProp.fromProto(proto.getLinearDimension(), fingerprint);
}
throw new IllegalStateException(
"Proto was not a recognised instance of ExtensionDimension");
}
@NonNull
static ExtensionDimension extensionDimensionFromProto(
@NonNull DimensionProto.ExtensionDimension proto) {
return extensionDimensionFromProto(proto, null);
}
}