Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 71 additions & 38 deletions docs/source/enable/constraints_layout.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ its layout system is helpful but not required.
Using Constraints
-----------------

:class:`ConstraintsContainer` is a :class:`Container` subclass which uses the
Cassowary_ constraint solver to determine the layout of its child
:class:`Component` instances. This is achieved by adding constraint variables
to the :class:`Component` class which define a simple box model:
:class:`~.ConstraintsContainer` is a :class:`~.Container` subclass which uses the
Kiwisolver_ constraint solver to determine the layout of its child
:class:`~.Component` instances. This is achieved by adding constraint variables
to the :class:`~.Component` class which define a simple box model:

* :attr:`layout_height`: The height of the component.
* :attr:`layout_width`: The width of the component.
Expand All @@ -26,7 +26,7 @@ to the :class:`Component` class which define a simple box model:
* :attr:`v_center`: The horizontal center line between the top and bottom edges

Additionally, there are some constraints which only exist on
:class:`ConstraintsContainer`:
:class:`~.ConstraintsContainer`:

* :attr:`contents_height`: The height of the container.
* :attr:`contents_width`: The width of the container.
Expand Down Expand Up @@ -56,9 +56,9 @@ layout constraints of a container:
return container

For more complicated layouts, the :attr:`layout_constraints` trait on a
:class:`ConstraintsContainer` can be a :class:`callable`. The function is
:class:`~.ConstraintsContainer` can be a :class:`callable`. The function is
passed a reference to the container and should return a list of
:class:`LinearContraints` objects or layout helper instances (as described below).
:class:`~.LinearContraints` objects or layout helper instances (as described below).

::

Expand Down Expand Up @@ -90,59 +90,70 @@ also available in Enable. The layout helpers are:

:data:`spacer`: Creates space between two adjacent components.

.. function:: horizontal(*components[, spacing=10])
.. function:: hbox(*components[, spacing=10, margins=...])
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why ... instead of 0?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because margins has several possible values which are enumerated below this line

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I thought this line was meant to indicate the default value that the parameter takes on, not to indicate the range of types that it accepts, which is why I thought it might read 0 instead.

It doesn't matter too much; I was just curious since I hadn't seen ellipsis used like this.


Takes a list of components and lines them up using their left and right edges.
Takes a list of components and lines them up using their left and right
edges and ensures that the components' heights match that of their
container.

:param components: A sequence of :class:`Component` or :class:`spacer` objects.
:param components: A sequence of :class:`~.Component` or :class:`~.spacer` objects.
:param spacing: How many pixels of inter-element spacing to use
:type spacing: integer >= 0
:param margins: An ``int``, ``tuple`` of ints, or :class:`enable.layout.geometry.Box`
of ints >= 0 which indicate how many pixels of margin to add around
the bounds of the box. The default is 0.

.. function:: vertical(*components[, spacing=10])
.. function:: vbox(*components[, spacing=10, margins=...])

Takes a list of components and lines them up using their top and bottom edges.
Takes a list of components and lines them up using their top and bottom
edges and ensures that the components' widths match each other.

:param components: A sequence of :class:`Component` or :class:`spacer` objects.
:param components: A sequence of :class:`~.Component` or :class:`~.spacer` objects.
:param spacing: How many pixels of inter-element spacing to use
:type spacing: integer >= 0
:param margins: An ``int``, ``tuple`` of ints, or :class:`enable.layout.geometry.Box`
of ints >= 0 which indicate how many pixels of margin to add around
the bounds of the box. The default is 0.

.. function:: hbox(*components[, spacing=10, margins=...])
.. function:: horizontal(*components[, spacing=10])

Like :func:`horizontal`, but ensures the height of components matches the container.
Like :func:`hbox`, but does not ensure that the heights of components match
each other.

:param components: A sequence of :class:`Component` or :class:`spacer` objects.
Takes a list of components and lines them up using their left and right
edges.

:param components: A sequence of :class:`~.Component` or :class:`~.spacer` objects.
:param spacing: How many pixels of inter-element spacing to use
:type spacing: integer >= 0
:param margins: An `int`, `tuple` of ints, or :class:`Box` of ints >= 0 which
indicate how many pixels of margin to add around the bounds
of the box. The default is 0.

.. function:: vbox(*components[, spacing=10, margins=...])
.. function:: vertical(*components[, spacing=10])

Like :func:`vertical`, but ensures the width of components matches the container.
Like :func:`vbox`, but does not ensure that the widths of components match
each other.

:param components: A sequence of :class:`Component` or :class:`spacer` objects.
Takes a list of components and lines them up using their top and bottom
edges.

:param components: A sequence of :class:`~.Component` or :class:`~.spacer` objects.
:param spacing: How many pixels of inter-element spacing to use
:type spacing: integer >= 0
:param margins: An `int`, `tuple` of ints, or :class:`Box` of ints >= 0 which
indicate how many pixels of margin to add around the bounds
of the box. The default is 0.

.. function:: align(anchor, *components[, spacing=10])

Aligns a single constraint across multiple components.

:param anchor: The name of a constraint variable that exists on all of the
`components`.
:param components: A sequence of :class:`Component` objects. Spacers are not allowed.
``components``.
:param components: A sequence of :class:`~.Component` objects. Spacers are not allowed.
:param spacing: How many pixels of inter-element spacing to use
:type spacing: integer >= 0

.. function:: grid(*rows[, row_align='', row_spacing=10, column_align='', column_spacing=10, margins=...])

Creates an NxM grid of components. Components may span multiple columns or rows.

:param rows: A sequence of sequences of :class:`Component` objects
:param rows: A sequence of sequences of :class:`~.Component` objects
:param row_align: The name of a constraint variable on an item. If given,
it is used to add constraints on the alignment of items
in a row. The constraints will only be applied to items
Expand All @@ -160,26 +171,48 @@ also available in Enable. The layout helpers are:
:param column_spacing: Indicates how many pixels of space should be placed
between columns in the grid. The default is 10.
:type column_spacing: integer >= 0
:param margins: An `int`, `tuple` of ints, or :class:`Box` of ints >= 0 which
indicate how many pixels of margin to add around the bounds
of the box. The default is 0.
:param margins: An ``int``, ``tuple`` of ints, or :class:`enable.layout.geometry.Box`
of ints >= 0 which indicate how many pixels of margin to add around
the bounds of the box. The default is 0.


Fine Tuning Layouts
-------------------

:class:`Component` defines a :class:`Tuple` trait :attr:`layout_size_hint` which
:class:`~.Component` defines a :class:`~.Tuple` trait :attr:`layout_size_hint` which
controls the minimum size of a component when it's part of a contraints layout.
Additionally, :class:`Component` defines some strength traits that can be used
Additionally, :class:`~.Component` defines some strength traits that can be used
to fine tune the behavior of a component instance during layout. They are:

* :attr:`hug_height`: How strongly a component prefers the height of its size hint when it could grow.
* :attr:`hug_width`: How strongly a component prefers the width of its size hint when it could grow.
* :attr:`resist_height`: How strongly a component resists its height being made smaller than its size hint.
* :attr:`resist_width`: How strongly a component resists its width being made smaller than its size hint.

The allow values for these strengths are: `'required'`, `'strong'`, `'medium'`,
and `'weak'`.

.. _Cassowary: http://www.cs.washington.edu/research/constraints/cassowary/
.. _Enaml: http://docs.enthought.com/enaml/
The allow values for these strengths are: ``'required'``, ``'strong'``, ``'medium'``,
and ``'weak'``.

Contrained Layout Pitfalls
--------------------------

* The :attr:`auto_size` trait of :class:`~.Container` is *completely ignored* by
constrained layout. Just ignore it.
* The :attr:`bounds` trait of a :class:`~.Component` which is a child of a
:class:`~.ConstraintsContainer` is *not considered* when generating a layout.
One should instead specify a minimum size with :attr:`layout_size_hint` and/or
add constraints which reference the component's :attr:`layout_height` or
:attr:`layout_width` traits.
* Similarly, the :attr:`position` trait of a :class:`~.Component` which is a
child of a :class:`~.ConstraintsContainer` is overwritten by the constraint
solver and not considered. Add constraints which reference the component's
:attr:`left` or :attr:`top` traits if you want to explicitly control the
final value of :attr:`position` (also :attr:`right`, :attr:`top`,
:attr:`v_center`, and :attr:`h_center` can influence the layout position)
* If a child :class:`~.Component` has zero :attr:`width` or :attr:`height`
after the container's :py:meth:`refresh` is called, that usually means the
layout is not sufficiently constrained. In that case, you need to add more
constraints to the container's :attr:`layout_constraints`.


.. _Kiwisolver: https://kiwisolver.readthedocs.io/en/latest/
.. _Enaml: https://enaml.readthedocs.io/en/latest/