stretchable by Example¶
The following is a tour of the various features of stretchable and how to use them.
For a detailed reference, see API Reference.
Building Node Trees¶
You can chain stretchable.Node.add() and create a node tree like this:
from stretchable import Node
from stretchable.style import PCT, AUTO
root = Node(
margin=20,
size=(500, 300),
).add(
Node(border=5, size=(50*PCT, AUTO)),
Node(padding=10*PCT, size=50*PCT)
)
You can also create each node separately and then add child nodes:
from stretchable import Node
from stretchable.style import PCT, AUTO
root = Node(
margin=20,
size=(500, 300),
)
child_1 = Node(border=5, size=(50*PCT, AUTO))
root.append(child_1)
child_2 = Node(padding=10*PCT, size=50*PCT)
root.append(child_2)
Configuring Styles¶
Styles can be specified in different ways, as illustrated here:
from stretchable import Node, Style
from strechable.style import SizePointsPercentAuto
# Using style keyword arguments on the Node constructor:
node = Node(key="content", min_size=SizePointsPercentAuto(width=300))
# Creating a Style instance explicitly:
node = Node(key="content", style=Style(min_size=SizePointsPercentAuto(width=300))
Similarly, style arguments that specify a geometry can be specified in different ways, as illustrated here:
from stretchable import Node, Style
from strechable.style import PCT, PT, AUTO
# The following all produce the same result:
# (floats/ints are automatically interpreted as points, PT)
node = Node(key="content", min_size=(300, AUTO))
node = Node(key="content", min_size=SizePointsPercentAuto(width=300))
node = Node(key="content", min_size=SizePointsPercentAuto(width=300*PT))
# Using percentages, both of these produce the same result:
node = Node(key="content", min_size=(AUTO, 50*PCT))
node = Node(key="content", min_size=SizePointsPercentAuto(height=50*PCT))
Locating Nodes¶
Suppose you have a tree of nodes that looks like this (with the stretchable.Node.key of each node as shown):
You can use stretchable.Node.find() to locate the nodes as illustrated here:
# Assume you've created a node tree and have a reference to the root node:
canvas_node = ...
# Get the header node
header_node = canvas_node.find("header")
# Get the content node using absolute location:
# (you could use any node in the tree, not just node_header())
content_node = header_node.find("/main/content")
# Get the footer node using relative location:
footer_node = content_node.find("../../header")
# Get the right sidebar node using relative location and indices:
right_sidebar_note = footer_node.find("../1/2")
You can get the address of each node from the stretchable.Node.address property.
Retrieve Layout¶
Use stretchable.Node.compute_layout() on the root node to compute (or recompute) the layout. The layout of the node and all child nodes will be computed. If only part of the node tree has changed, you can invoke layout computation on part of the node tree.
After the layout has been computed, you can get the position and size of each of the nodes using stretchable.Node.get_box():
from stretchable import Edge
root = ... # Build node tree
root.compute_layout()
node = root.find("/main/content")
# Get the position and size of the border box of a node relative to the parent node,
# with 'y' measured from the top of the container (increasing downwards).
border_box = node.border_box
# The same box can be gotten using get_box() without any arguments (or the defaults).
border_box = node.get_box()
# Get the content box relative to the parent node, 'y' measured from the top.
content_box = node.get_box(Edge.CONTENT)
# Get the content box relative to the root, 'y' measured from the bottom
# (increasing upwards)
content_box = node.get_box(Edge.CONTENT, relative=False, flip_y=True)
Using measure Functions¶
Todo
Add examples of using measure functions.