1// Composable layout elements that can be combined together to create renderable
2// UI layouts.
3syntax = "proto3";
4
5package androidx.wear.tiles.testing.proto;
6
7import "color.proto";
8import "dimension.proto";
9import "modifiers.proto";
10import "types.proto";
11
12option java_package = "androidx.wear.tiles.testing.proto";
13option java_outer_classname = "LayoutElementProto";
14
15// The horizontal alignment of an element within its container.
16enum HorizontalAlignment {
17  // Horizontal alignment is undefined.
18  HORIZONTAL_ALIGN_UNDEFINED = 0;
19
20  // Horizontally align to the left.
21  HORIZONTAL_ALIGN_LEFT = 1;
22
23  // Horizontally align to center.
24  HORIZONTAL_ALIGN_CENTER = 2;
25
26  // Horizontally align to the right.
27  HORIZONTAL_ALIGN_RIGHT = 3;
28
29  // Horizontally align to the content start (left in LTR layouts, right in RTL
30  // layouts).
31  HORIZONTAL_ALIGN_START = 4;
32
33  // Horizontally align to the content end (right in LTR layouts, left in RTL
34  // layouts).
35  HORIZONTAL_ALIGN_END = 5;
36}
37
38// An extensible HorizontalAlignment property.
39message HorizontalAlignmentProp {
40  // The value
41  HorizontalAlignment value = 1;
42}
43
44// The vertical alignment of an element within its container.
45enum VerticalAlignment {
46  // Vertical alignment is undefined.
47  VERTICAL_ALIGN_UNDEFINED = 0;
48
49  // Vertically align to the top.
50  VERTICAL_ALIGN_TOP = 1;
51
52  // Vertically align to center.
53  VERTICAL_ALIGN_CENTER = 2;
54
55  // Vertically align to the bottom.
56  VERTICAL_ALIGN_BOTTOM = 3;
57}
58
59// An extensible VerticalAlignment property.
60message VerticalAlignmentProp {
61  // The value.
62  VerticalAlignment value = 1;
63}
64
65// The weight to be applied to the font.
66enum FontWeight {
67  // Font weight is undefined.
68  FONT_WEIGHT_UNDEFINED = 0;
69
70  // Normal font weight.
71  FONT_WEIGHT_NORMAL = 400;
72
73  // Bold font weight.
74  FONT_WEIGHT_BOLD = 700;
75}
76
77// An extensible FontWeight property.
78message FontWeightProp {
79  // The value.
80  FontWeight value = 1;
81}
82
83// The styling of a font (e.g. font size, and metrics).
84message FontStyle {
85  // The size of the font, in scaled pixels (sp). If not specified, defaults to
86  // the size of the system's "body" font.
87  SpProp size = 1;
88
89  // Whether the text should be rendered in a italic typeface. If not specified,
90  // defaults to "false".
91  BoolProp italic = 2;
92
93  // Whether the text should be rendered with an underline. If not specified,
94  // defaults to "false".
95  BoolProp underline = 3;
96
97  // The text color. If not defined, defaults to white.
98  ColorProp color = 4;
99
100  // The weight of the font. If the provided value is not supported on a
101  // platform, the nearest supported value will be used. If not defined, or
102  // when set to an invalid value, defaults to "normal".
103  FontWeightProp weight = 5;
104
105  // The text letter-spacing. Positive numbers increase the space between
106  // letters while negative numbers tighten the space. If not specified,
107  // defaults to 0.
108  EmProp letter_spacing = 6;
109}
110
111// Alignment of a text element.
112enum TextAlignment {
113  // Alignment is undefined.
114  TEXT_ALIGN_UNDEFINED = 0;
115
116  // Align to the "start" of the Text element (left in LTR layouts, right in
117  // RTL layouts).
118  TEXT_ALIGN_START = 1;
119
120  // Align to the center of the Text element.
121  TEXT_ALIGN_CENTER = 2;
122
123  // Align to the "end" of the Text element (right in LTR layouts, left in RTL
124  // layouts).
125  TEXT_ALIGN_END = 3;
126}
127
128// An extensible TextAlignment property.
129message TextAlignmentProp {
130  // The value.
131  TextAlignment value = 1;
132}
133
134// How text that will not fit inside the bounds of a Text element will be
135// handled.
136//
137// TODO(b/175536688): Rename this to align with Spannable
138enum TextOverflow {
139  // Overflow behavior is undefined.
140  TEXT_OVERFLOW_UNDEFINED = 0;
141
142  // Truncate the text to fit inside of the Text element's bounds. If text is
143  // truncated, it will be truncated on a word boundary.
144  TEXT_OVERFLOW_TRUNCATE = 1;
145
146  // Truncate the text to fit in the Text element's bounds, but add an ellipsis
147  // (i.e. ...) to the end of the text if it has been truncated.
148  TEXT_OVERFLOW_ELLIPSIZE_END = 2;
149}
150
151// An extensible TextOverflow property.
152message TextOverflowProp {
153  // The value.
154  TextOverflow value = 1;
155}
156
157// The anchor position of an Arc's elements. This is used to specify how
158// elements added to an Arc should be laid out with respect to anchor_angle.
159//
160// As an example, assume that the following diagrams are wrapped to an arc, and
161// each represents an Arc element containing a single Text element. The Text
162// element's anchor_angle is "0" for all cases.
163//
164// ```
165// ARC_ANCHOR_START:
166// -180                                0                                    180
167//                                     Hello World!
168//
169//
170// ARC_ANCHOR_CENTER:
171// -180                                0                                    180
172//                                Hello World!
173//
174// ARC_ANCHOR_END:
175// -180                                0                                    180
176//                          Hello World!
177// ```
178enum ArcAnchorType {
179  // Anchor position is undefined.
180  ARC_ANCHOR_UNDEFINED = 0;
181
182  // Anchor at the start of the elements. This will cause elements added to an
183  // arc to begin at the given anchor_angle, and sweep around to the right.
184  ARC_ANCHOR_START = 1;
185
186  // Anchor at the center of the elements. This will cause the center of the
187  // whole set of elements added to an arc to be pinned at the given
188  // anchor_angle.
189  ARC_ANCHOR_CENTER = 2;
190
191  // Anchor at the end of the elements. This will cause the set of elements
192  // inside the arc to end at the specified anchor_angle, i.e. all elements
193  // should be to the left of anchor_angle.
194  ARC_ANCHOR_END = 3;
195}
196
197// An extensible ArcAnchorType property.
198message ArcAnchorTypeProp {
199  // The value.
200  ArcAnchorType value = 1;
201}
202
203// A text string.
204message Text {
205  // The text to render.
206  StringProp text = 1;
207
208  // The style of font to use (size, bold etc). If not specified, defaults to
209  // the platform's default body font.
210  FontStyle font_style = 2;
211
212  // Modifiers for this element.
213  Modifiers modifiers = 3;
214
215  // The maximum number of lines that can be represented by the Text element.
216  // If not defined, the Text element will be treated as a single-line element.
217  Int32Prop max_lines = 4;
218
219  // Alignment of the text within its bounds. Note that a Text element will size
220  // itself to wrap its contents, so this option is meaningless for single-line
221  // text (for that, use alignment of the outer container). For multi-line text,
222  // however, this will set the alignment of lines relative to the Text element
223  // bounds. If not defined, defaults to TEXT_ALIGN_CENTER.
224  TextAlignmentProp multiline_alignment = 5;
225
226  // How to handle text which overflows the bound of the Text element.
227  // A Text element will grow as large as possible inside its parent container
228  // (while still respecting max_lines); if it cannot grow large  enough to
229  // render all of its text, the text which cannot fit inside its container will
230  // be truncated. If not defined, defaults to TEXT_OVERFLOW_TRUNCATE.
231  TextOverflowProp overflow = 6;
232
233  // The explicit height between lines of text. This is equivalent to the
234  // vertical distance between subsequent baselines. If not specified, defaults
235  // the font's recommended interline spacing.
236  SpProp line_height = 7;
237}
238
239// How content which does not match the dimensions of its bounds (e.g. an image
240// resource being drawn inside an Image) will be resized to fit its bounds.
241enum ContentScaleMode {
242  // Content scaling is undefined.
243  CONTENT_SCALE_MODE_UNDEFINED = 0;
244
245  // Content will be scaled to fit inside its bounds, proportionally. As an
246  // example, If a 10x5 image was going to be drawn inside a 50x50 Image
247  // element, the actual image resource would be drawn as a 50x25 image,
248  // centered within the 50x50 bounds.
249  CONTENT_SCALE_MODE_FIT = 1;
250
251  // Content will be resized proportionally so it completely fills its bounds,
252  // and anything outside of the bounds will be cropped. As an example, if a
253  // 10x5 image was going to be drawn inside a 50x50 Image element, the image
254  // resource would be drawn as a 100x50 image, centered within its bounds (and
255  // with 25px cropped from both the left and right sides).
256  CONTENT_SCALE_MODE_CROP = 2;
257
258  // Content will be resized to fill its bounds, without taking into account the
259  // aspect ratio. If a 10x5 image was going to be drawn inside a 50x50 Image
260  // element, the image would be drawn as a 50x50 image, stretched vertically.
261  CONTENT_SCALE_MODE_FILL_BOUNDS = 3;
262}
263
264// An extensible ContentScaleMode property.
265message ContentScaleModeProp {
266  ContentScaleMode value = 1;
267}
268
269// An image.
270//
271// Images used in this element must exist in the resource bundle that
272// corresponds to this layout. Images must have their dimension specified, and
273// will be rendered at this width and height, regardless of their native
274// dimension.
275message Image {
276  // The resource_id of the image to render. This must exist in the supplied
277  // resource bundle.
278  StringProp resource_id = 1;
279
280  // The width of this image. If not defined, the image will not be rendered.
281  ImageDimension width = 2;
282
283  // The height of this image. If not defined, the image will not be rendered.
284  ImageDimension height = 3;
285
286  // How to scale the image resource inside the bounds specified by width/height
287  // if its size does not match those bounds. Defaults to
288  // CONTENT_SCALE_MODE_FIT.
289  ContentScaleModeProp content_scale_mode = 4;
290
291  // Modifiers for this element.
292  Modifiers modifiers = 5;
293}
294
295// A simple spacer, typically used to provide padding between adjacent elements.
296message Spacer {
297  // The width of this Spacer. When this is added as the direct child of an Arc,
298  // this must be specified as an angular dimension, otherwise a linear
299  // dimension must be used. If not defined, defaults to 0.
300  SpacerDimension width = 1;
301
302  // The height of this spacer. If not defined, defaults to 0.
303  SpacerDimension height = 2;
304
305  // Modifiers for this element.
306  Modifiers modifiers = 3;
307}
308
309// A container which stacks all of its children on top of one another. This also
310// allows to add a background color, or to have a border around them with some
311// padding.
312message Box {
313  // The child element(s) to wrap.
314  repeated LayoutElement contents = 1;
315
316  // The height of this Box. If not defined, this will size itself to fit all of
317  // its children (i.e. a WrappedDimension).
318  ContainerDimension height = 2;
319
320  // The width of this Box. If not defined, this will size itself to fit all of
321  // its children (i.e. a WrappedDimension).
322  ContainerDimension width = 3;
323
324  // The horizontal alignment of the element inside this Box. If not defined,
325  // defaults to HORIZONTAL_ALIGN_CENTER.
326  HorizontalAlignmentProp horizontal_alignment = 4;
327
328  // The vertical alignment of the element inside this Box. If not defined,
329  // defaults to VERTICAL_ALIGN_CENTER.
330  VerticalAlignmentProp vertical_alignment = 5;
331
332  // Modifiers for this element.
333  Modifiers modifiers = 6;
334}
335
336// A portion of text which can be added to a Span. Two different SpanText
337// elements on the same line will be aligned to the same baseline, regardless of
338// the size of each SpanText.
339message SpanText {
340  // The text to render.
341  StringProp text = 1;
342
343  // The style of font to use (size, bold etc). If not specified, defaults to
344  // the platform's default body font.
345  FontStyle font_style = 2;
346
347  // Modifiers for this element.
348  SpanModifiers modifiers = 3;
349}
350
351// An image which can be added to a Span.
352message SpanImage {
353  // The resource_id of the image to render. This must exist in the supplied
354  // resource bundle.
355  StringProp resource_id = 1;
356
357  // The width of this image. If not defined, the image will not be rendered.
358  DpProp width = 2;
359
360  // The height of this image. If not defined, the image will not be rendered.
361  DpProp height = 3;
362
363  // Modifiers for this element.
364  SpanModifiers modifiers = 4;
365}
366
367// A single Span. Each Span forms part of a larger Spannable widget. At the
368// moment, the only widgets which can be added to Spannable containers are
369// SpanText and SpanImage elements.
370message Span {
371  oneof inner {
372    SpanText text = 1;
373    SpanImage image = 2;
374  }
375}
376
377// A container of Span elements. Currently, this only supports Text elements,
378// where each individual Span can have different styling applied to it but the
379// resulting text will flow naturally. This allows sections of a paragraph of
380// text to have different styling applied to it, for example, making one or two
381// words bold or italic.
382message Spannable {
383  // The Span elements that form this Spannable.
384  repeated Span spans = 1;
385
386  // Modifiers for this element.
387  Modifiers modifiers = 2;
388
389  // The maximum number of lines that can be represented by the Spannable
390  // element. If not defined, the Spannable element will be treated as a
391  // single-line element.
392  Int32Prop max_lines = 3;
393
394  // Alignment of the Spannable content within its bounds. Note that a Spannable
395  // element will size itself to wrap its contents, so this option is
396  // meaningless for single-line content (for that, use alignment of the outer
397  // container). For multi-line content, however, this will set the alignment of
398  // lines relative to the Spannable element bounds. If not defined, defaults to
399  // TEXT_ALIGN_CENTER.
400  HorizontalAlignmentProp multiline_alignment = 4;
401
402  // How to handle content which overflows the bound of the Spannable element.
403  // A Spannable element will grow as large as possible inside its parent
404  // container (while still respecting max_lines); if it cannot grow large
405  // enough to render all of its content, the content which cannot fit inside
406  // its container will  be truncated. If not defined, defaults to
407  // TEXT_OVERFLOW_TRUNCATE.
408  TextOverflowProp overflow = 5;
409
410  // Extra spacing to add between each line. This will apply to all
411  // spans regardless of their font size. This is in addition to original
412  // line heights. Note that this won't add any additional space before the
413  // first line or after the last line. The default value is zero and negative
414  // values will decrease the interline spacing.
415  SpProp line_spacing = 6;
416}
417
418// A column of elements. Each child element will be laid out vertically, one
419// after another (i.e. stacking down). This element will size itself to the
420// smallest size required to hold all of its children (e.g. if it contains three
421// elements sized 10x10, 20x20 and 30x30, the resulting column will be 30x60).
422//
423// If specified, horizontal_alignment can be used to control the gravity inside
424// the container, affecting the horizontal placement of children whose width are
425// smaller than the resulting column width.
426message Column {
427  // The list of child elements to place inside this Column.
428  repeated LayoutElement contents = 1;
429
430  // The horizontal alignment of elements inside this column, if they are
431  // narrower than the resulting width of the column. If not defined, defaults
432  // to HORIZONTAL_ALIGN_CENTER.
433  HorizontalAlignmentProp horizontal_alignment = 2;
434
435  // The width of this column. If not defined, this will size itself to fit
436  // all of its children (i.e. a WrappedDimension).
437  ContainerDimension width = 3;
438
439  // The height of this column. If not defined, this will size itself to fit
440  // all of its children (i.e. a WrappedDimension).
441  ContainerDimension height = 4;
442
443  // Modifiers for this element.
444  Modifiers modifiers = 5;
445}
446
447// A row of elements. Each child will be laid out horizontally, one after
448// another (i.e. stacking to the right). This element will size itself to the
449// smallest size required to hold all of its children (e.g. if it contains three
450// elements sized 10x10, 20x20 and 30x30, the resulting row will be 60x30).
451//
452// If specified, vertical_alignment can be used to control the gravity inside
453// the container, affecting the vertical placement of children whose width are
454// smaller than the resulting row height.
455message Row {
456  // The list of child elements to place inside this Row.
457  repeated LayoutElement contents = 1;
458
459  // The vertical alignment of elements inside this row, if they are narrower
460  // than the resulting height of the row. If not defined, defaults to
461  // VERTICAL_ALIGN_CENTER.
462  VerticalAlignmentProp vertical_alignment = 2;
463
464  // The width of this row. If not defined, this will size itself to fit
465  // all of its children (i.e. a WrappedDimension).
466  ContainerDimension width = 3;
467
468  // The height of this row. If not defined, this will size itself to fit
469  // all of its children (i.e. a WrappedDimension).
470  ContainerDimension height = 4;
471
472  // Modifiers for this element.
473  Modifiers modifiers = 5;
474}
475
476// An arc container. This container will fill itself to a circle, which fits
477// inside its parent container, and all of its children will be placed on that
478// circle. The fields anchor_angle and anchor_type can be used to specify where
479// to draw children within this circle.
480message Arc {
481  // Contents of this container.
482  repeated ArcLayoutElement contents = 1;
483
484  // The angle for the anchor, used with anchor_type to determine where to draw
485  // children. Note that 0 degrees is the 12 o clock position on a device, and
486  // the angle sweeps clockwise. If not defined, defaults to 0 degrees.
487  //
488  // Values do not have to be clamped to the range 0-360; values less than 0
489  // degrees will sweep anti-clockwise (i.e. -90 degrees is equivalent to 270
490  // degrees), and values >360 will be be placed at X mod 360 degrees.
491  DegreesProp anchor_angle = 2;
492
493  // How to align the contents of this container relative to anchor_angle. See
494  // the descriptions of options in ArcAnchorType for more information. If not
495  // defined, defaults to ARC_ANCHOR_CENTER.
496  ArcAnchorTypeProp anchor_type = 3;
497
498  // Vertical alignment of elements within the arc. If the Arc's thickness is
499  // larger than the thickness of the element being drawn, this controls whether
500  // the element should be drawn towards the inner or outer edge of the arc, or
501  // drawn in the center.
502  // If not defined, defaults to VERTICAL_ALIGN_CENTER
503  VerticalAlignmentProp vertical_align = 4;
504
505  // Modifiers for this element.
506  Modifiers modifiers = 5;
507}
508
509// A text element that can be used in an Arc.
510message ArcText {
511  // The text to render.
512  StringProp text = 1;
513
514  // The style of font to use (size, bold etc). If not specified, defaults to
515  // the platform's default body font.
516  FontStyle font_style = 2;
517
518  // Modifiers for this element.
519  ArcModifiers modifiers = 3;
520}
521
522// A line that can be used in an Arc and renders as a round progress bar.
523message ArcLine {
524  // The length of this line, in degrees. If not defined, defaults to 0.
525  DegreesProp length = 1;
526
527  // The thickness of this line. If not defined, defaults to 0.
528  DpProp thickness = 2;
529
530  // The color of this line.
531  ColorProp color = 3;
532
533  // Modifiers for this element.
534  ArcModifiers modifiers = 4;
535}
536
537// A simple spacer used to provide padding between adjacent elements in an Arc.
538message ArcSpacer {
539  // The length of this spacer, in degrees. If not defined, defaults to 0.
540  DegreesProp length = 1;
541
542  // The thickness of this spacer, in DP. If not defined, defaults to 0.
543  DpProp thickness = 2;
544
545  // Modifiers for this element.
546  ArcModifiers modifiers = 3;
547}
548
549// A container that allows a standard LayoutElement to be added to an Arc.
550message ArcAdapter {
551  // The element to adapt to an Arc.
552  LayoutElement content = 1;
553
554  // Whether this adapter's contents should be rotated, according to its
555  // position in the arc or not. As an example, assume that an Image has been
556  // added to the arc, and ends up at the 3 o clock position. If rotate_contents
557  // = true, the image will be placed at the 3 o clock position, and will be
558  // rotated clockwise through 90 degrees. If rotate_contents = false, the image
559  // will be placed at the 3 o clock position, but itself will not be rotated.
560  // If not defined, defaults to false.
561  BoolProp rotate_contents = 2;
562}
563
564// The root of all layout elements. This exists to act as a holder for all of
565// the actual layout elements above.
566message LayoutElement {
567  oneof inner {
568    Column column = 1;
569    Row row = 2;
570    Box box = 3;
571    Spacer spacer = 4;
572    Text text = 5;
573    Image image = 6;
574    Arc arc = 7;
575    Spannable spannable = 8;
576  }
577}
578
579// The root of all elements that can be used in an Arc. This exists to act as a
580// holder for all of the actual arc layout elements above.
581message ArcLayoutElement {
582  oneof inner {
583    ArcText text = 1;
584    ArcLine line = 2;
585    ArcSpacer spacer = 3;
586    ArcAdapter adapter = 4;
587  }
588}
589
590// A complete layout.
591message Layout {
592  // The root element in the layout.
593  LayoutElement root = 1;
594}
595