layout¶
Layout managers position objects automatically. Select one with the layout=
argument to Patcher ("grid", "flow", "columnar"/"matrix",
"horizontal", "vertical") and call optimize_layout().
p = Patcher('patch.maxpat', layout="flow", flow_direction="vertical")
# ... add objects and lines ...
p.optimize_layout()
Layout management for py2max patches.
This subpackage provides various layout managers for automatic positioning of Max objects in patches:
- LayoutManager: Basic horizontal layout (deprecated)
- GridLayoutManager: Grid-based layout with clustering
- FlowLayoutManager: Signal flow-based hierarchical layout
- MatrixLayoutManager: Matrix/columnar layout for signal chains
- HorizontalLayoutManager: Legacy alias for GridLayoutManager (horizontal)
- VerticalLayoutManager: Legacy alias for GridLayoutManager (vertical)
LayoutManager ¶
Bases: AbstractLayoutManager
Basic horizontal layout manager.
Provides simple left-to-right object positioning with wrapping. This is a legacy layout manager; consider using GridLayoutManager for new projects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parent
|
AbstractPatcher
|
The parent patcher object. |
required |
pad
|
Optional[int]
|
Padding between objects (default: 48.0). |
None
|
box_width
|
Optional[int]
|
Default object width (default: 66.0). |
None
|
box_height
|
Optional[int]
|
Default object height (default: 22.0). |
None
|
comment_pad
|
Optional[int]
|
Padding for comments (default: 2). |
None
|
get_rect_from_maxclass ¶
Retrieve default rectangle for a Max object class.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
maxclass
|
str
|
The Max object class name. |
required |
Returns:
| Type | Description |
|---|---|
Optional[Rect]
|
Default Rect for the object class, or None if not found. |
box_dims ¶
Return an object's own (width, height) for repositioning.
Optimizers place objects on a uniform grid sized by box_width /
box_height, but they must not write back those defaults as the
object's size -- doing so squashes every UI object (dial, scope~,
function, live.*, comments) down to text-box dimensions (L2).
Read the object's existing rect and keep its real w/h, falling back to
the manager defaults only when it has no usable rect. Works whether the
rect is a Rect namedtuple (programmatic) or a plain list (loaded).
get_pos ¶
Get the next position for object placement.
Calculates the next position for an object based on the current layout state and optional object class defaults.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
maxclass
|
Optional[str]
|
Optional Max object class for size defaults. |
None
|
Returns:
| Type | Description |
|---|---|
Rect
|
Rect specifying the position and size for the next object. |
prevent_overlaps ¶
Iteratively push overlapping objects apart.
This method should be called after layout optimization to ensure no objects overlap. It uses an iterative approach where overlapping objects are pushed apart in the direction of their center offset.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
min_gap
|
float
|
Minimum gap between objects in pixels. |
10.0
|
max_iterations
|
int
|
Maximum number of iterations to prevent infinite loops. |
50
|
Returns:
| Type | Description |
|---|---|
int
|
Number of iterations performed (0 if no overlaps found). |
place_params ¶
Dock value/UI 'param' objects next to the single object they drive.
A param (number box, toggle, slider, dial, message, live.*) whose
outgoing connections all go to one non-param target is repositioned
adjacent to that target, perpendicular to the signal flow -- above the
target for a horizontal flow, to its left for a vertical flow -- and
aligned to the inlet it feeds. This keeps value controls with their
object instead of spread through the signal graph.
Runs after the main layout as the final placement pass. direction
defaults to the manager's flow_direction.
optimize_layout ¶
Arrange every object in the patch (batch, whole-patch layout).
This is py2max's batch layout entry point: it always performs a full
layout of the entire patch. Subclasses implement their algorithm in
_full_layout().
Interactive, per-edit ("incremental") relayout is intentionally out of
scope for py2max; it belongs to the editor/server that owns the live
editing session. See docs/auto-layout.md in py2max-server.
FlowLayoutManager ¶
Bases: LayoutManager
Advanced layout manager that analyzes signal flow topology.
This layout manager: - Analyzes patchline connections to understand signal flow - Groups related objects based on connection patterns - Uses hierarchical positioning with signal flow left-to-right or top-to-bottom - Minimizes line crossings and connection distances - Balances layout aesthetically while respecting functional relationships
get_relative_pos ¶
Returns a flow-optimized position for the object.
GridLayoutManager ¶
Bases: LayoutManager
Utility class to help with object layout in a grid pattern.
This layout manager supports both horizontal and vertical grid layouts: - Horizontal: objects fill from left to right and wrap to next row - Vertical: objects fill from top to bottom and wrap to next column
get_relative_pos ¶
Returns a relative position for the object based on flow direction.
HorizontalLayoutManager ¶
Bases: GridLayoutManager
Legacy horizontal layout manager. Use GridLayoutManager with flow_direction="horizontal" instead.
VerticalLayoutManager ¶
Bases: GridLayoutManager
Legacy vertical layout manager. Use GridLayoutManager with flow_direction="vertical" instead.
ColumnarLayoutManager ¶
Bases: MatrixLayoutManager
Functional-column layout: Controls -> Generators -> Processors -> Outputs.
A thin specialization of :class:MatrixLayoutManager pinned to column mode,
where objects are grouped by functional category into vertical columns rather
than by signal chain. Selected via Patcher(..., layout="columnar").
MatrixLayoutManager ¶
Bases: LayoutManager
Unified matrix/columnar layout manager with configurable flow direction.
This layout manager can organize objects in two different patterns based on flow_direction:
When flow_direction="column" (Columnar Layout):
Column 0: Controls/Inputs | Column 1: Generators | Column 2: Processors | Column 3: Outputs
[control0] | [gen0] | [proc0] | [output0]
[input0] | [gen1] | [proc1] | [output1]
[control1] | [gen2] | [proc2] | [output2]
When flow_direction="row" (Matrix Layout):
Row 0 (Inputs/Controls): [input0/control0] [input1/control1] [input2/control2] ...
Row 1 (Generators): [gen0] [gen1] [gen2] ...
Row 2 (Processors): [proc0] [proc1] [proc2] ...
Row 3 (Outputs): [output0] [output1] [output2] ...
In column mode, objects are grouped by functional category into vertical columns. In row mode, signal chains form columns while functional categories form rows.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parent
|
AbstractPatcher
|
The parent patcher object. |
required |
pad
|
Optional[int]
|
Padding between objects (default: 48.0). |
None
|
box_width
|
Optional[int]
|
Default object width (default: 66.0). |
None
|
box_height
|
Optional[int]
|
Default object height (default: 22.0). |
None
|
comment_pad
|
Optional[int]
|
Padding for comments (default: 2). |
None
|
flow_direction
|
str
|
Layout direction - "column" or "row" (default: "row"). |
'row'
|
num_dimensions
|
int
|
Number of columns (in column mode) or rows (in row mode) (default: 4). |
4
|
dimension_spacing
|
float
|
Extra spacing between dimensions (default: 100.0). |
100.0
|
num_columns
property
writable
¶
Number of functional columns (column mode); alias of num_dimensions.
get_relative_pos ¶
Returns a position based on flow_direction setting.
get_signal_chain_info ¶
Get information about detected signal chains.
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
Dictionary with signal chain analysis results. |
GraphLayoutManager ¶
Bases: LayoutManager
Position boxes with an external graph-layout engine.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parent
|
AbstractPatcher
|
the parent patcher. |
required |
algorithm
|
str
|
one of :attr: |
required |
span
|
Optional[float]
|
target size in px for the longest side of the normalized layout. Defaults to a value scaled by object count so boxes do not overlap. |
None
|