# Widgets! Pixlet comes with a number of built-in _Widgets_. These are used to describe how data should be laid out, presented and finally rendered to an image file. The easiest way to get started is probably to take a look at some of the [examples](../examples/), and then refer to the detailed Widget documentation (this document) when the need arises. For animated widgets like Marquee, you can also call `frame_count()` to work out how many frames are required to display the whole animation. You can also call `size()` on dynamically-sized widgets like Text to get the width and height. ## Colors When specifying colors, use a CSS-like hexadecimal color specification or a `Color` object from [`color.star`](modules.md#pixlet-module-color). Pixlet supports `#rgb`, `#rrggbb`, `#rgba`, and `#rrggbbaa` hex color specifications. Color objects are useful for programmatically manipulating colors. ```starlark load("render.star", "render") load("color.star", "color") def main(): # Use a hex string red_box = render.Box(color="#f00") # Use a Color object blue = color.rgb(0, 0, 255) # could also be defined as color.hex("#00f") or color.hsv(0, 0, 1) blue_box = render.Box(color=blue) # ... ``` ## Animation Animation turns a list of children into an animation, where each child is a frame. FIXME: Behaviour when children themselves are animated is a bit weird. Think and fix. #### Attributes | Name | Type | Description | Required | | --- | --- | --- | --- | | `children` | `[Widget]` | Children to use as frames in the animation | N | #### Example ``` render.Animation( children=[ render.Box(width=10, height=10, color="#300"), render.Box(width=12, height=12, color="#500"), render.Box(width=14, height=14, color="#700"), render.Box(width=16, height=16, color="#900"), render.Box(width=18, height=18, color="#b00"), ], ) ``` ![](img/widget_Animation_0.gif) ## Arc Arc draws an arc. The arc is centered at (x, y). #### Attributes | Name | Type | Description | Required | | --- | --- | --- | --- | | `x` | `float / int` | The x-coordinate of the center of the arc. | **Y** | | `y` | `float / int` | The y-coordinate of the center of the arc. | **Y** | | `radius` | `float / int` | The radius of the arc. | **Y** | | `start_angle` | `float / int` | The starting angle of the arc, in radians. | **Y** | | `end_angle` | `float / int` | The ending angle of the arc, in radians. | **Y** | | `color` | `color` | The color of the arc. | **Y** | | `width` | `float / int` | The width of the arc. | **Y** | | `antialias` | `bool` | Enables antialiased stroke rendering. | N | #### Example ``` render.Arc( x = 10, y = 10, radius = 10, start_angle = 0, end_angle = 3.14 * 1.5, width = 3, color = "#0ff", ) ``` ![](img/widget_Arc_0.gif) ## Box A Box is a rectangular widget that can hold a child widget. Boxes are transparent unless `color` is provided. They expand to fill all available space, unless `width` and/or `height` is provided. Boxes can have a `child`, which will be centered in the box, and the child can be padded (via `padding`). #### Attributes | Name | Type | Description | Required | | --- | --- | --- | --- | | `child` | `Widget` | Child to center inside box | N | | `width` | `int` | Limits Box width | N | | `height` | `int` | Limits Box height | N | | `padding` | `int` | Padding around the child widget | N | | `color` | `color` | Background color | N | #### Example ``` render.Box( color="#00f", child=render.Box( width=20, height=10, color="#f00", ) ) ``` ![](img/widget_Box_0.gif) ## Circle Circle draws a circle with the given `diameter` and `color`. If a `child` widget is provided, it is drawn in the center of the circle. #### Attributes | Name | Type | Description | Required | | --- | --- | --- | --- | | `color` | `color` | Fill color | **Y** | | `diameter` | `int` | Diameter of the circle | **Y** | | `child` | `Widget` | Widget to place in the center of the circle | N | #### Example ``` render.Circle( color="#666", diameter=30, child=render.Circle(color="#0ff", diameter=10), ) ``` ![](img/widget_Circle_0.gif) ## Column Column lays out and draws its children vertically (in a column). By default, a Column is as small as possible, while still holding all its children. However, if `expanded` is set, the Column will fill all available space vertically. The width of a Column is always that of its widest child. Alignment along the vertical main axis is controlled by passing one of the following `main_align` values: - `"start"`: place children at the beginning of the column - `"end"`: place children at the end of the column - `"center"`: place children in the middle of the column - `"space_between"`: place equal space between children - `"space_evenly"`: equal space between children and before/after first/last child - `"space_around"`: equal space between children, and half of that before/after first/last child Alignment along the horizontal cross axis is controlled by passing one of the following `cross_align` values: - `"start"`: place children at the left - `"end"`: place children at the right - `"center"`: place children in the center #### Attributes | Name | Type | Description | Required | | --- | --- | --- | --- | | `children` | `[Widget]` | Child widgets to lay out | **Y** | | `main_align` | `str` | Alignment along vertical main axis | N | | `cross_align` | `str` | Alignment along horizontal cross axis | N | | `expanded` | `bool` | Column should expand to fill all available vertical space | N | #### Example ``` render.Column( children=[ render.Box(width=10, height=8, color="#a00"), render.Box(width=14, height=6, color="#0a0"), render.Box(width=16, height=4, color="#00a"), ], ) ``` ![](img/widget_Column_0.gif) #### Example ``` render.Column( expanded=True, main_align="space_around", cross_align="center", children=[ render.Box(width=10, height=8, color="#a00"), render.Box(width=14, height=6, color="#0a0"), render.Box(width=16, height=4, color="#00a"), ], ) ``` ![](img/widget_Column_1.gif) ## Emoji Emoji renders a single emoji at a specified height, maintaining aspect ratio. This allows for rendering emojis much larger than the standard 10x10 pixel size used in text rendering. #### Attributes | Name | Type | Description | Required | | --- | --- | --- | --- | | `emoji` | `str` | The Unicode emoji sequence to render | **Y** | | `width` | `int` | Scale emoji to this width | N | | `height` | `int` | Scale emoji to this height | N | #### Example ``` render.Emoji(emoji="😀", height=32) # Large smiley face ``` ![](img/widget_Emoji_0.gif) ## Image Image renders the binary image data passed via `src`. Supported formats include PNG, JPEG, GIF, and SVG. If `width` or `height` are set, the image will be scaled accordingly, with nearest neighbor interpolation. Otherwise the image's original dimensions are used. If the image data encodes an animated GIF, the Image instance will also be animated. Frame delay (in milliseconds) can be read from the `delay` attribute. #### Attributes | Name | Type | Description | Required | | --- | --- | --- | --- | | `src` | `str / bytes` | Binary image data or SVG text | **Y** | | `width` | `int` | Scale image to this width | N | | `height` | `int` | Scale image to this height | N | | `delay` | `int` | (Read-only) Frame delay in ms, for animated GIFs | N | | `hold_frames` | `int` | Number of render frames to hold each animation frame, default is 1. | N | ## Line Line draws a line from (x1, y1) to (x2, y2). #### Attributes | Name | Type | Description | Required | | --- | --- | --- | --- | | `x1` | `float / int` | The x-coordinate of the starting point. | **Y** | | `y1` | `float / int` | The y-coordinate of the starting point. | **Y** | | `x2` | `float / int` | The x-coordinate of the ending point. | **Y** | | `y2` | `float / int` | The y-coordinate of the ending point. | **Y** | | `color` | `color` | The color of the line. | **Y** | | `width` | `float / int` | The width of the line. | **Y** | | `antialias` | `bool` | Enables antialiased stroke rendering. | N | #### Example ``` render.Line( x1 = 0, y1 = 0, x2 = 63, y2 = 31, width = 1, color = "#fff", ) ``` ![](img/widget_Line_0.gif) ## Marquee Marquee scrolls its child horizontally or vertically. The `scroll_direction` will be 'horizontal' and will scroll from right to left if left empty, if specified as 'vertical' the Marquee will scroll from bottom to top. In horizontal mode the height of the Marquee will be that of its child, but its `width` must be specified explicitly. In vertical mode the width will be that of its child but the `height` must be specified explicitly. If the child's width fits fully, it will not scroll. The `offset_start` and `offset_end` parameters control the position of the child in the beginning and the end of the animation. Alignment for a child that fits fully along the horizontal/vertical axis is controlled by passing one of the following `align` values: - `"start"`: place child at the left/top - `"end"`: place child at the right/bottom - `"center"`: place child at the center #### Attributes | Name | Type | Description | Required | | --- | --- | --- | --- | | `child` | `Widget` | Widget to potentially scroll | **Y** | | `width` | `int` | Width of the Marquee, required for horizontal | N | | `height` | `int` | Height of the Marquee, required for vertical | N | | `offset_start` | `int` | Position of child at beginning of animation | N | | `offset_end` | `int` | Position of child at end of animation | N | | `scroll_direction` | `str` | Direction to scroll, 'vertical' or 'horizontal', default is horizontal | N | | `align` | `str` | Alignment when contents fit on screen, 'start', 'center' or 'end', default is start | N | | `delay` | `int` | Delay the scroll of the animation by a certain number of frames, default is 0 | N | #### Example ``` render.Marquee( width=64, child=render.Text("this won't fit in 64 pixels"), offset_start=5, offset_end=32, ) ``` ![](img/widget_Marquee_0.gif) ## Padding Padding places padding around its child. If the `pad` attribute is a single integer, that amount of padding will be placed on all sides of the child. If it's a 4-tuple `(left, top, right, bottom)`, then padding will be placed on the sides accordingly. #### Attributes | Name | Type | Description | Required | | --- | --- | --- | --- | | `child` | `Widget` | The Widget to place padding around | **Y** | | `pad` | `int / tuple of 3 ints` | Padding around the child | N | | `expanded` | `bool` | This is a confusing parameter | N | | `color` | `color` | Background color. | N | ## PieChart PieChart draws a circular pie chart of size `diameter`. It takes two arguments for the data: parallel lists `colors` and `weights` representing the shading and relative sizes of each data entry. #### Attributes | Name | Type | Description | Required | | --- | --- | --- | --- | | `colors` | `[color]` | List of color hex codes | **Y** | | `weights` | `[float]` | List of numbers corresponding to the relative size of each color | **Y** | | `diameter` | `int` | Diameter of the circle | **Y** | #### Example ``` render.PieChart( colors = [ "#fff", "#0f0", "#00f" ], weights = [ 180, 135, 45 ], diameter = 30, ) ``` ![](img/widget_PieChart_0.gif) ## Plot Plot is a widget that draws a data series. #### Attributes | Name | Type | Description | Required | | --- | --- | --- | --- | | `data` | `[(float, float)]` | A list of 2-tuples of numbers | **Y** | | `width` | `int` | Limits Plot width | **Y** | | `height` | `int` | Limits Plot height | **Y** | | `color` | `color` | Line color, default is '#fff' | N | | `color_inverted` | `color` | Line color for Y-values below 0 | N | | `x_lim` | `(float, float)` | Limit X-axis to a range | N | | `y_lim` | `(float, float)` | Limit Y-axis to a range | N | | `fill` | `bool` | Paint surface between line and X-axis | N | | `chart_type` | `str` | Specifies the type of chart to render, "scatter" or "line", default is "line" | N | | `fill_color` | `color` | Fill color for Y-values above 0 | N | | `fill_color_inverted` | `color` | Fill color for Y-values below 0 | N | #### Example ``` render.Plot( data = [ (0, 3.35), (1, 2.15), (2, 2.37), (3, -0.31), (4, -3.53), (5, 1.31), (6, -1.3), (7, 4.60), (8, 3.33), (9, 5.92), ], width = 64, height = 32, color = "#0f0", color_inverted = "#f00", x_lim = (0, 9), y_lim = (-5, 7), fill = True, ) ``` ![](img/widget_Plot_0.gif) ## Polygon Polygon draws a polygon. #### Attributes | Name | Type | Description | Required | | --- | --- | --- | --- | | `vertices` | `[(float, float)]` | A list of (x, y) tuples representing the vertices of the polygon. | **Y** | | `fill_color` | `color` | The color used to fill the polygon. | N | | `stroke_color` | `color` | The color used to draw the polygon's stroke. | N | | `stroke_width` | `float / int` | The width of the polygon's stroke. | N | | `antialias` | `bool` | Enables antialiased stroke rendering. | N | #### Example ``` render.Polygon( vertices = [(0, 0), (20, 0), (20, 10), (0, 10)], fill_color = "#00f", stroke_color = "#fff", stroke_width = 1, ) ``` ![](img/widget_Polygon_0.gif) ## Root Root is the top level of every Widget tree. The child widget, and all its descendants, will be drawn on a 64x32 canvas. Root places its child in the upper left corner of the canvas. If the tree contains animated widgets, the resulting animation will run with _delay_ milliseconds per frame. If the tree holds time sensitive information which must never be displayed past a certain point in time, pass _MaxAge_ to specify an expiration time in seconds. Display devices use this to avoid displaying stale data in the event of e.g. connectivity issues. #### Attributes | Name | Type | Description | Required | | --- | --- | --- | --- | | `child` | `Widget` | Widget to render | **Y** | | `delay` | `int` | Frame delay in milliseconds | N | | `max_age` | `int` | Expiration time in seconds | N | | `show_full_animation` | `bool` | Request animation is shown in full, regardless of app cycle speed. | N | ## Row Row lays out and draws its children horizontally (in a row). By default, a Row is as small as possible, while still holding all its children. However, if `expanded` is set, the Row will fill all available space horizontally. The height of a Row is always that of its tallest child. Alignment along the horizontal main axis is controlled by passing one of the following `main_align` values: - `"start"`: place children at the beginning of the row - `"end"`: place children at the end of the row - `"center"`: place children in the middle of the row - `"space_between"`: place equal space between children - `"space_evenly"`: equal space between children and before/after first/last child - `"space_around"`: equal space between children, and half of that before/after first/last child Alignment along the vertical cross axis is controlled by passing one of the following `cross_align` values: - `"start"`: place children at the top - `"end"`: place children at the bottom - `"center"`: place children at the center #### Attributes | Name | Type | Description | Required | | --- | --- | --- | --- | | `children` | `[Widget]` | Child widgets to lay out | **Y** | | `main_align` | `str` | Alignment along horizontal main axis | N | | `cross_align` | `str` | Alignment along vertical cross axis | N | | `expanded` | `bool` | Row should expand to fill all available horizontal space | N | #### Example ``` render.Row( children=[ render.Box(width=10, height=8, color="#a00"), render.Box(width=14, height=6, color="#0a0"), render.Box(width=16, height=4, color="#00a"), ], ) ``` ![](img/widget_Row_0.gif) #### Example ``` render.Row( expanded=True, main_align="space_between", cross_align="end", children=[ render.Box(width=10, height=8, color="#a00"), render.Box(width=14, height=6, color="#0a0"), render.Box(width=16, height=4, color="#00a"), ], ) ``` ![](img/widget_Row_1.gif) ## Sequence Sequence renders a list of child widgets in sequence. Each child widget is rendered for the duration of its frame count, then the next child wiget in the list will be rendered and so on. It comes in quite useful when chaining animations. If you want to know more about that, go check out the [animation](animation.md) documentation. #### Attributes | Name | Type | Description | Required | | --- | --- | --- | --- | | `children` | `[Widget]` | List of child widgets | **Y** | #### Example ``` render.Sequence( children = [ render.Box(width=10, height=10, color="#f00"), render.Box(width=10, height=10, color="#0f0"), render.Box(width=10, height=10, color="#00f"), ], ) ``` ![](img/widget_Sequence_0.gif) ## Stack Stack draws its children on top of each other. Just like a stack of pancakes, except with Widgets instead of pancakes. The Stack will be given a width and height sufficient to fit all its children. #### Attributes | Name | Type | Description | Required | | --- | --- | --- | --- | | `children` | `[Widget]` | Widgets to stack | **Y** | #### Example ``` render.Stack( children=[ render.Box(width=50, height=25, color="#911"), render.Text("hello there"), render.Box(width=4, height=32, color="#119"), ], ) ``` ![](img/widget_Stack_0.gif) ## Text Text draws a string of text on a single line. By default, the text will use the "tb-8" font, but other fonts can be chosen via the `font` attribute. The `height` and `offset` parameters allow fine tuning of the vertical layout of the string. Take a look at the [font documentation](fonts.md) for more information. #### Attributes | Name | Type | Description | Required | | --- | --- | --- | --- | | `content` | `str` | The text string to draw | **Y** | | `font` | `str` | Desired font face | N | | `height` | `int` | Limits height of the area on which text is drawn | N | | `offset` | `int` | Shifts position of text vertically. | N | | `color` | `color` | Desired font color | N | #### Example ``` render.Text(content="Tidbyt!", color="#099") ``` ![](img/widget_Text_0.gif) ## WrappedText WrappedText draws multi-line text. The optional `width` and `height` parameters limit the drawing area. If not set, WrappedText will use as much vertical and horizontal space as possible to fit the text. Alignment of the text is controlled by passing one of the following `align` values: - `"left"`: align text to the left - `"center"`: align text in the center - `"right"`: align text to the right #### Attributes | Name | Type | Description | Required | | --- | --- | --- | --- | | `content` | `str` | The text string to draw | **Y** | | `font` | `str` | Desired font face | N | | `height` | `int` | Limits height of the area on which text may be drawn | N | | `width` | `int` | Limits width of the area on which text may be drawn | N | | `linespacing` | `int` | Controls spacing between lines | N | | `color` | `color` | Desired font color | N | | `align` | `str` | Text alignment | N | | `wordbreak` | `bool` | If true, long words that exceed the width will be broken to fit | N | #### Example ``` render.WrappedText( content="this is a multi-line text string", width=50, color="#fa0", ) ``` ![](img/widget_WrappedText_0.gif)