Source code for enaml.widgets.form

#------------------------------------------------------------------------------
#  Copyright (c) 2012, Enthought, Inc.
#  All rights reserved.
#------------------------------------------------------------------------------
from traits.api import Instance, Str

from enaml.layout.constraint_variable import ConstraintVariable
from enaml.layout.layout_helpers import align, hbox, vbox

from .container import  Container


[docs]class Form(Container): """ A Container subclass that arranges its children in two columns. The left column is typically Labels (but this is not a requirement). The right are the actual widgets for data entry. The children should be in alternating label/widget order. If there are an odd number of children, the last child will span both columns. The Form provides an extra constraint variable, 'midline', which is used as the alignment anchor for the columns. """ #: The ConstraintVariable giving the midline along which the labels #: and widgets are aligned. midline = Instance(ConstraintVariable) def _midline_default(self): return ConstraintVariable('midline', self.object_id) #: The strength for the form layout constraints. # FIXME: Use an Enum. layout_strength = Str('strong') #: A form hugs its height strongly by default. Forms are typcially #: used to display vertical arrangements of widgets, with forms #: often being stacked on top of each other. For this case, hugging #: the height is desired. hug_height = 'strong' def _component_constraints(self): """ Supplies the constraints which layout the children in a two column form. """ # FIXME: do something sensible when children are not visible. children = list(self.widgets) labels = children[::2] widgets = children[1::2] n_labels = len(labels) n_widgets = len(widgets) if n_labels != n_widgets: if n_labels > n_widgets: odd_child = labels.pop() else: odd_child = widgets.pop() else: odd_child = None layout_strength = self.layout_strength constraints = [] # Align the left side of each widget with the midline constraint # variable of the form. midline = self.midline for widget in widgets: cn = (widget.left == midline) | layout_strength constraints.append(cn) # Arrange each label/widget pair horizontally in the form # XXX this is a highly inefficient way to generate these # constraints. It starts to be noticeably slow when the # form has around 20 rows. This can be done better. labels_widgets = zip(labels, widgets) vbox_args = [hbox(label, widget) for label, widget in labels_widgets] if odd_child is not None: vbox_args.append(odd_child) constraints.append(vbox(*vbox_args)) for label, widget in labels_widgets: # FIXME: baselines would be much better. constraints.append(align('v_center', label, widget) | layout_strength) return constraints def _default_constraints(self): """ Overridden parent class method which returns an empty list. This disables the vbox constraints supplied by the superclass Container. All Form constraints are generated by the '_component_constraints' method. """ return []