1 /* 2 * Copyright 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 @file:JvmName("LayoutStringUtil") 17 18 package androidx.wear.protolayout.types 19 20 import androidx.annotation.RestrictTo 21 import androidx.wear.protolayout.LayoutElementBuilders.TEXT_ALIGN_CENTER 22 import androidx.wear.protolayout.LayoutElementBuilders.TextAlignment 23 import androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint 24 import androidx.wear.protolayout.TypeBuilders.StringProp 25 import androidx.wear.protolayout.expression.DynamicBuilders.DynamicString 26 import androidx.wear.protolayout.expression.RequiresSchemaVersion 27 import java.util.Objects 28 29 /** 30 * Static or dynamic string value for layout fields. 31 * 32 * This can be used on layout string fields with data binding support. 33 */ 34 class LayoutString 35 private constructor( 36 @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) val prop: StringProp, 37 /** 38 * When [dynamicValue] is used, this allows correctly measuring layout Text element size and 39 * aligning text to ensure that the layout is of a known size during the layout pass regardless 40 * of the [dynamicValue] String. 41 */ 42 val layoutConstraint: StringLayoutConstraint? = null 43 ) { 44 /** 45 * The static value. If [dynamicValue] is not null this will be used as the default value for 46 * when [dynamicValue] can't be resolved. 47 */ 48 val staticValue: String = prop.value 49 /** The dynamic value. If this can't be resolved [staticValue] will be used during rendering. */ 50 val dynamicValue: DynamicString? = prop.dynamicValue 51 52 /** Creates an instance for a static String value. */ 53 constructor(staticValue: String) : this(StringProp.Builder(staticValue).build()) 54 55 /** 56 * Creates an instance for a [DynamicString] value with a static value fallback and a set of 57 * layout constraints for the dynamic value. 58 * 59 * @param staticValue the static value that can be used when the `dynamicValue` can't be 60 * resolved. 61 * @param dynamicValue the dynamic value. If this value can be resolved, the `staticValue` won't 62 * be used. 63 * @param layoutConstraint used to correctly measure layout Text element size and align text to 64 * ensure that the layout is of a known size during the layout pass regardless of the 65 * `dynamicValue` String. 66 */ 67 @RequiresSchemaVersion(major = 1, minor = 200) 68 constructor( 69 staticValue: String, 70 dynamicValue: DynamicString, 71 layoutConstraint: StringLayoutConstraint 72 ) : this( 73 StringProp.Builder(staticValue).setDynamicValue(dynamicValue).build(), 74 layoutConstraint 75 ) 76 equalsnull77 override fun equals(other: Any?) = 78 this === other || 79 (other is LayoutString && 80 prop == other.prop && 81 layoutConstraint == other.layoutConstraint) 82 83 override fun hashCode() = Objects.hash(prop, layoutConstraint) 84 85 override fun toString() = "LayoutString(prop=$prop, layoutConstraint=$layoutConstraint)" 86 } 87 88 /** Extension for creating a [LayoutString] from a String. */ 89 val String.layoutString: LayoutString 90 @JvmName("createLayoutString") get() = LayoutString(this) 91 92 /** 93 * Extension for creating a [LayoutString] from a [DynamicString] 94 * 95 * @param staticValue the static value that can be used when the `dynamicValue` can't be resolved. 96 * @param layoutConstraint used to correctly measure layout Text element size and align text to 97 * ensure that the layout is of a known size during the layout pass regardless of the 98 * `dynamicValue` String. 99 */ 100 @JvmName("createLayoutString") 101 @RequiresSchemaVersion(major = 1, minor = 200) 102 fun DynamicString.asLayoutString(staticValue: String, layoutConstraint: StringLayoutConstraint) = 103 LayoutString(staticValue, this, layoutConstraint) 104 105 /** 106 * Specifies layout constraints for to use for layout measurement in presence of dynamic values. 107 * 108 * @param longestPattern the text string to use as the pattern for the (graphically) longest text 109 * that can be laid out. Used to ensure that the layout is of a known size during the layout pass. 110 * @param alignment the alignment of the actual text within the space reserved by `longestPattern` 111 */ 112 @JvmOverloads 113 @RequiresSchemaVersion(major = 1, minor = 200) 114 fun stringLayoutConstraint( 115 longestPattern: String, 116 @TextAlignment alignment: Int = TEXT_ALIGN_CENTER 117 ) = StringLayoutConstraint.Builder(longestPattern).setAlignment(alignment).build() 118 119 /** 120 * Extension for creating a [StringLayoutConstraint] from a String. `this` will be used as 121 * `longestPattern`. 122 * 123 * @param alignment the alignment of the actual text within the space reserved by `longestPattern` 124 */ 125 @RequiresSchemaVersion(major = 1, minor = 200) 126 fun String.asLayoutConstraint(@TextAlignment alignment: Int = TEXT_ALIGN_CENTER) = 127 stringLayoutConstraint(this, alignment) 128