mirror of
https://git.lynn.is/Gwen/python-layout.git
synced 2024-01-13 01:31:55 +01:00
509 lines
15 KiB
Markdown
509 lines
15 KiB
Markdown
# Example
|
|
|
|
```python
|
|
from layout import Document, Flex, Text, TextAlign, TextVerticalAlign,
|
|
|
|
FlexAlignContent, FlexDirection, FlexAlignItems, FlexWrap
|
|
|
|
doc = Document(
|
|
width=800,
|
|
height=400,
|
|
bg_color=(206, 249, 242, 255),
|
|
content=Flex(
|
|
direction=FlexDirection.ROW,
|
|
wrap=FlexWrap.WRAP,
|
|
align_items=FlexAlignItems.STRETCH,
|
|
align_content=FlexAlignContent.STRETCH,
|
|
gap=20,
|
|
padding=20,
|
|
contents=[
|
|
Text(
|
|
text="ITEM 1",
|
|
bg_color=(4, 231, 98, 128),
|
|
width=100,
|
|
flex_grow=1,
|
|
flex_shrink=1,
|
|
text_align=TextAlign.CENTER,
|
|
vertical_text_align=TextVerticalAlign.MIDDLE
|
|
),
|
|
Text(
|
|
text="ITEM 2",
|
|
bg_color=(34, 49, 39, 128),
|
|
width=300,
|
|
flex_grow=1,
|
|
flex_shrink=1,
|
|
text_align=TextAlign.CENTER,
|
|
vertical_text_align=TextVerticalAlign.MIDDLE
|
|
),
|
|
Text(
|
|
text="ITEM 3",
|
|
bg_color=(220, 0, 115, 128),
|
|
width=200,
|
|
flex_grow=1,
|
|
flex_shrink=1,
|
|
text_align=TextAlign.CENTER,
|
|
vertical_text_align=TextVerticalAlign.MIDDLE
|
|
),
|
|
Text(
|
|
text="ITEM 4",
|
|
bg_color=(0, 139, 248, 128),
|
|
width=400,
|
|
flex_grow=1,
|
|
flex_shrink=1,
|
|
text_align=TextAlign.CENTER,
|
|
vertical_text_align=TextVerticalAlign.MIDDLE
|
|
),
|
|
Text(
|
|
text="ITEM 5",
|
|
bg_color=(71, 0, 99, 128),
|
|
width=250,
|
|
flex_grow=1,
|
|
flex_shrink=1,
|
|
text_align=TextAlign.CENTER,
|
|
vertical_text_align=TextVerticalAlign.MIDDLE
|
|
),
|
|
]
|
|
)
|
|
)
|
|
|
|
image = doc.get_image()
|
|
image.show()
|
|
```
|
|
|
|
# Layouts
|
|
|
|
## Layout
|
|
|
|
Base layout class, do not use directly. Provides the following properties:
|
|
|
|
```python
|
|
from layout import Layout
|
|
|
|
Layout(
|
|
width=None, # width of the layout element
|
|
height=None, # height of the layout element
|
|
min_width=None, # minimum width of the layout element
|
|
min_height=None, # minimum height of the layout element
|
|
max_width=None, # maximum width of the layout element
|
|
max_height=None, # maximum height of the layout element
|
|
fg_color=None, # foreground color (inherited)
|
|
bg_color=None, # background color (inherited)
|
|
border_color=None, # border color (see section Borders)
|
|
border_width=0, # border width (see section Borders)
|
|
border_radius=0, # border radius (see section Borders)
|
|
padding=0, # padding of the layout element
|
|
font=None, # font for texts (inherited)
|
|
overflow=None, # allow overflow of layout content
|
|
left=None, # left absolute position (in children of Container layout)
|
|
top=None, # top absolute position (in children of Container layout)
|
|
right=None, # right absolute position (in children of Container layout)
|
|
bottom=None, # bottom absolute position (in children of Container layout)
|
|
flex_grow=0, # flex grow proportion (in children of Flex layout)
|
|
flex_shrink=0, # flex grow proportion (in children of Flex layout)
|
|
)
|
|
|
|
```
|
|
|
|
### Borders
|
|
|
|
Borders are painted over the background but below potentially overflowing content.
|
|
Every border property can be a single value or a tuple (except color) or list of up to four values.
|
|
Multiple values for border width and color are given in the order (`left`, `top`, `right`, `bottom`).
|
|
Multiple values for border radius are given in the order (`top-left`, `top-right`, `bottom-right`, `bottom-left`).
|
|
The border color property can only be given as a single value or list of values, not as a tuple, since colors are
|
|
defined as RGBA-tuples and a tuple value is interpreted as a single color.
|
|
|
|
## Container
|
|
|
|
Simple layout container with absolute and automatic positioning.
|
|
Children with any of their `left`/`top`/`right`/`bottom` properties set to something other than `None` are positioned
|
|
absolutely.
|
|
Other children are positioned automatically.
|
|
|
|
```python
|
|
from layout import Container
|
|
|
|
Container(
|
|
contents=[], # child layouts
|
|
)
|
|
```
|
|
|
|
## Flex
|
|
|
|
Flexible layout container roughly based on the CSS flex specification.
|
|
Children of this layout can use the `flex_grow` and `flex_shrink` properties.
|
|
|
|
```python
|
|
from layout import Flex, FlexDirection, FlexWrap, FlexJustify, FlexAlignItems, FlexAlignContent
|
|
|
|
Flex(
|
|
contents=[], # child layouts
|
|
direction=FlexDirection.ROW,
|
|
wrap=FlexWrap.NO_WRAP,
|
|
justify=FlexJustify.START,
|
|
align_items=FlexAlignItems.START,
|
|
align_content=FlexAlignContent.START,
|
|
gap=0, # gap between flex items
|
|
)
|
|
```
|
|
|
|
The properties `direction`, `wrap`, `justify`, `align_items`, `align_content` and `gap` work roughly like their CSS
|
|
counterparts.
|
|
|
|
Flex layout arranges items into one or multiple lines. A line is a row in `ROW`/`ROW_REVERSE` and a column
|
|
in `COLUMN`/`COLUMN_REVERSE` direction.
|
|
The "main axis" is the axis in which direction the items are arranged, i.e. the x-axis for rows and the y-axis for
|
|
columns.
|
|
The "cross axis" is the other axis.
|
|
|
|
### FlexDirection
|
|
|
|
Specifies the direction in which child layouts (items) are arranged in the layout.
|
|
Other flex properties with values like `START` and `END` depend on the direction.
|
|
|
|
#### FlexDirection.ROW
|
|
|
|
Items are arranged in rows.
|
|
|
|
#### FlexDirection.ROW_REVERSE
|
|
|
|
Items are arranged in rows, in reverse order.
|
|
The item that is first in the `contents` list is at the end and vice versa.
|
|
Items are still *rendered* in the same order as they appear in the `contents` list, so overlapping items will be
|
|
rendered on top of each other in that order.
|
|
|
|
#### FlexDirection.COLUMN
|
|
|
|
Items are arranged in columns.
|
|
|
|
#### FlexDirection.COLUMN_REVERSE
|
|
|
|
Like `ROW_REVERSE`, but with columns.
|
|
|
|
### FlexWrap
|
|
|
|
Specifies whether and how flex items can wrap into multiple lines (rows/columns).
|
|
|
|
#### FlexWrap.NO_WRAP
|
|
|
|
Items can not wrap, all items are displayed in one line.
|
|
|
|
#### FlexWrap.WRAP
|
|
|
|
Items can wrap into multiple lines if they do not fit into the available space.
|
|
|
|
#### FlexWrap.WRAP_REVERSE
|
|
|
|
like `WRAP`, but lines are arranged in reverse order.
|
|
|
|
### FlexJustify
|
|
|
|
This property corresponds to `justify-content` in CSS flex layouts.
|
|
It determines how items within a line are arranged on the main axis if there is space left over along the main axis
|
|
after growing/shrinking items.
|
|
|
|
#### FlexJustify.START
|
|
|
|
The available space is at the end of the line, the items at the beginning.
|
|
|
|
#### FlexJustify.END
|
|
|
|
The available space is at the beginning of the line, the items at the end.
|
|
|
|
#### FlexJustify.CENTER
|
|
|
|
The available space is equally distributed at the beginning and end of the line, the items are in the center.
|
|
|
|
#### FlexJustify.SPACE_BETWEEN
|
|
|
|
The available space is equally distributed between the items, the first and last item are at the beginning and end of
|
|
the line.
|
|
|
|
#### FlexJustify.SPACE_AROUND
|
|
|
|
The available space is equally distributed to the items, and for each item equally distributed before and after the
|
|
item.
|
|
There is twice as much space between two items as there is before the first and after the last item.
|
|
|
|
#### FlexJustify.SPACE_EVENLY
|
|
|
|
The available space is equally distributed before, after and between the items.
|
|
|
|
### FlexAlignItems
|
|
|
|
Specifies how items within a line are arranged on the cross axis if they don't fill the entire cross size of the line.
|
|
|
|
#### FlexAlignItems.START
|
|
|
|
Items are arranged at the start of the line, i.e. at the top for rows and at the left for columns.
|
|
|
|
#### FlexAlignItems.END
|
|
|
|
Items are arranged at the end of the line, i.e. at the bottom for rows and at the right for columns.
|
|
|
|
#### FlexAlignItems.CENTER
|
|
|
|
Items are arranged at the center of the line.
|
|
|
|
#### FlexAlignItems.STRETCH
|
|
|
|
Items are stretched out to fill the line.
|
|
|
|
### FlexAlignContent
|
|
|
|
Specifies how multiple lines are arranged on the cross axis within the layout when they don't fill the cross size of the
|
|
layout.
|
|
This is only relevant for layouts with multiple lines, a single line is always stretched to fill the layout (the items
|
|
within such a line can be controlled with `FlexAlignItems`).
|
|
|
|
#### FlexAlignContent.START
|
|
|
|
The lines are at the beginning of the layout, i.e. at the top for rows and at the left for columns.
|
|
|
|
#### FlexAlignContent.END
|
|
|
|
The lines are at the end of the layout, i.e. at the bottom for rows and at the right for columns.
|
|
|
|
#### FlexAlignContent.CENTER
|
|
|
|
The lines are at the center of the layout.
|
|
|
|
#### FlexAlignContent.STRETCH
|
|
|
|
The lines are stretched to fill the available space. The available space is distributed equally between the lines.
|
|
|
|
#### FlexAlignContent.SPACE_BETWEEN
|
|
|
|
The available space is distributed equally between the lines but not around them.
|
|
|
|
#### FlexAlignContent.SPACE_AROUND
|
|
|
|
The available space is distributed equally to the lines, and for each line distributed equally before and after that
|
|
line.
|
|
The space between two lines is twice as much as the space before the first and after the last line.
|
|
|
|
#### FlexAlignContent.SPACE_EVENLY
|
|
|
|
The available space is distributed equally before, between and after the lines.
|
|
|
|
## Box
|
|
|
|
This layout can render a title over its own top border.
|
|
|
|
```python
|
|
from layout import Box, BoxTitleAnchor
|
|
|
|
Box(
|
|
title=None,
|
|
title_font=None,
|
|
title_color=None,
|
|
title_anchor=BoxTitleAnchor.LEFT, # anchor for positioning
|
|
title_position=0, # x position of the title relative to the anchor
|
|
title_padding=0, # additional space to remove from the border on the left and right of the text
|
|
content=None,
|
|
)
|
|
```
|
|
|
|
### BoxTitleAnchor
|
|
|
|
Where to anchor the title along the top border.
|
|
The top left and top right border radii are subtracted from the available space.
|
|
|
|
#### BoxTitleAnchor.LEFT
|
|
|
|
The title is anchored at the left edge of the border, plus the top left border radius.
|
|
|
|
#### BoxTitleAnchor.CENTER
|
|
|
|
The title is anchored in the middle of the border.
|
|
|
|
#### BoxTitleAnchor.RIGHT
|
|
|
|
The title is anchored at the right edge of the border, minus the top right border radius.
|
|
|
|
## Text
|
|
|
|
This layout can render text.
|
|
The layout algorithm is somewhat inefficient and arranging large amounts of texts can take a while.
|
|
The line-breaking algorithm is very simplistic.
|
|
Whitespace at the beginning (if left-aligned), end (if right-aligned) or begining and end (if center-aligned) is not
|
|
rendered.
|
|
|
|
```python
|
|
from layout import Text, TextAlign, TextVerticalAlign, TextWrap
|
|
|
|
Text(
|
|
text=None,
|
|
# can be provided as a single string or as a list of lines, if a list then lines must not contain line breaks
|
|
text_align=TextAlign.LEFT,
|
|
vertical_text_align=TextVerticalAlign.TOP,
|
|
text_wrap=TextWrap.NO_WRAP,
|
|
line_spacing=0 # spacing between the end of one line and the beginning of the next
|
|
)
|
|
```
|
|
|
|
### TextAlign
|
|
|
|
How each line is aligned within the available horizontal space.
|
|
|
|
#### TextAlign.LEFT
|
|
|
|
#### TextAlign.CENTER
|
|
|
|
#### TextAlign.RIGHT
|
|
|
|
### TextVerticalAlign
|
|
|
|
How all the lines together are aligned within the available vertical space.
|
|
|
|
#### TextVerticalAlign.TOP
|
|
|
|
#### TextVerticalAlign.MIDDLE
|
|
|
|
#### TextVerticalAlign.BOTTOM
|
|
|
|
### TextWrap
|
|
|
|
#### TextWrap.NO_WRAP
|
|
|
|
Text is not automatically wrapped to fit into the available horizontal space, but explicit line breaks are respected.
|
|
|
|
#### TextWrap.ONLY_WORDS
|
|
|
|
Text is wrapped on word boundaries. Words that are too long to fit into a single line overflow.
|
|
|
|
#### TextWrap.PREFER_WORDS
|
|
|
|
Text is wrapped on word boundaries, and words that are too long to fit into a single line are wrapped as well.
|
|
|
|
#### TextWrap.EVERYWHERE
|
|
|
|
Lines are filled up as much as possible and text is wrapped wherever necessary.
|
|
|
|
## Image
|
|
|
|
```python
|
|
from layout import Image, ImageMode, ImageAnchor
|
|
|
|
Image(
|
|
image=None,
|
|
mode=ImageMode.ORIGINAL,
|
|
scale=1, # can be a number or a tuple of x- and y-scale
|
|
position=ImageAnchor.TOP_LEFT, # anchor for positioning
|
|
offset_x=0, # horizontal position of the image relative to the anchor
|
|
offset_y=0, # vertical position of the image relative to the anchor
|
|
)
|
|
|
|
```
|
|
|
|
### ImageMode
|
|
|
|
How the image is displayed.
|
|
This also affects how much space this layout tries to take up:
|
|
With `ORIGINAL` mode both width and height correspond to the (scaled) width and height of the image.
|
|
With `STRETCH_X` and `REPEAT_X` mode the height corresponds to the (scaled) height of the image, but the width is 0
|
|
unless forced otherwise.
|
|
With `STRETCH_Y` and `REPEAT_Y` mode the width corresponds to the (scaled) width of the image, but the height is 0
|
|
unless forced otherwise.
|
|
With all other modes the width and height are 0 unless forced otherwise.
|
|
All modes except `STRETCH`, `CONTAIN` and `COVER` respect the `scale` property in some way.
|
|
|
|
#### ImageMode.ORIGINAL
|
|
|
|
The image is rendered at its original size, optionally scaled by the `scale` property.
|
|
|
|
#### ImageMode.STRETCH
|
|
|
|
The image is stretched to fill the available space.
|
|
|
|
#### ImageMode.STRETCH_X
|
|
|
|
The image is stretched in the x-axis to fill the available space and unmodified in the y-axis.
|
|
|
|
#### ImageMode.STRETCH_Y
|
|
|
|
The image is stretched in the y-axis to fill the available space and unmodified in the x-axis.
|
|
|
|
#### ImageMode.CONTAIN
|
|
|
|
The image is scaled proportionally to fill the available space as much as possible without being cut off.
|
|
The image can still be cut off in places by positioning it or by rounded corners of the container.
|
|
This can make the image smaller if the available space is smaller than the original image size.
|
|
|
|
#### ImageMode.COVER
|
|
|
|
The image is scaled proportionally to fill the available space completely.
|
|
This can make the image smaller if the available space is smaller than the original image size.
|
|
|
|
#### ImageMode.REPEAT
|
|
|
|
The image is repeated on both axes to fill the available space.
|
|
|
|
#### ImageMode.REPEAT_X
|
|
|
|
The image is repeated on the x-axis to fill the available space.
|
|
|
|
#### ImageMode.REPEAT_Y
|
|
|
|
The image is repeated on the y-axis to fill the available space.
|
|
|
|
#### ImageMode.REPEAT_X_STRETCH
|
|
|
|
The image is repeated on the x-axis and stretched on the y-axis to fill the available space.
|
|
|
|
#### ImageMode.REPEAT_Y_STRETCH
|
|
|
|
The image is repeated on the y-axis and stretched on the x-axis to fill the available space.
|
|
|
|
#### ImageMode.REPEAT_X_FILL
|
|
|
|
The image is scaled like with `CONTAIN` on the y-axis and then repeated along the x-axis to fill the remaining space.
|
|
|
|
#### ImageMode.REPEAT_Y_FILL
|
|
|
|
The image is scaled like with `CONTAIN` on the x-axis and then repeated along the y-axis to fill the remaining space.
|
|
|
|
### ImageAnchor
|
|
|
|
Where the image is anchored for positioning with `offset_x` and `offset_y`.
|
|
|
|
#### ImageAnchor.TOP_LEFT
|
|
|
|
#### ImageAnchor.TOP_CENTER
|
|
|
|
#### ImageAnchor.TOP_RIGHT
|
|
|
|
#### ImageAnchor.MIDDLE_LEFT
|
|
|
|
#### ImageAnchor.MIDDLE_CENTER
|
|
|
|
#### ImageAnchor.MIDDLE_RIGHT
|
|
|
|
#### ImageAnchor.BOTTOM_LEFT
|
|
|
|
#### ImageAnchor.BOTTOM_CENTER
|
|
|
|
#### ImageAnchor.BOTTOM_RIGHT
|
|
|
|
# custom layouts
|
|
|
|
A layout should extend the `Layout` class and implement the following methods:
|
|
|
|
|
|
|
|
# possible future features
|
|
|
|
## border modes
|
|
|
|
option to render borders as outlines instead (i.e. not taking up layout space), with the following options:
|
|
|
|
- `NORMAL`: border takes up layout space
|
|
- `OUTLINE_INSIDE`: border is an overlay that takes up no space, inside of the layout rect
|
|
- `OUTLINE_OUTSIDE`: border is an overlay that takes up no space, outside of the layout rect
|
|
(only visible with overflow=true)
|
|
- `OUTLINE_CENTERED`: border is an overlay that takes up no space, centered on the layout rect
|
|
(only completely visible with overflow=true)
|
|
|
|
## border styles
|
|
|
|
border styles like dotted, dashed, inset etc like in CSS |