Exemplo n.º 1
0
    def _add_items(self, content, outer=None):
        """Adds a list of Item objects, creating a layout if needed.  Return
           the outermost layout.
        """
        # Get local references to various objects we need:
        ui = self.ui
        info = ui.info
        handler = ui.handler

        group = self.group
        show_left = group.show_left
        padding = group.padding
        columns = group.columns

        # See if a label is needed.
        show_labels = False
        for item in content:
            show_labels |= item.show_label

        # See if a grid layout is needed.
        if show_labels or columns > 1:
            inner = GridLayout(columns * 2, len(content))
            inner.setSpacing(True)
            inner.setSizeUndefined()

            if outer is None:
                outer = inner
            else:
                outer.addComponent(inner)

            row = 0
            if show_left:
                label_alignment = Alignment.MIDDLE_RIGHT
            else:
                label_alignment = Alignment.MIDDLE_LEFT

        else:
            # Use the existing layout if there is one.
            if outer is None:
                if self.horizontal:
                    outer = HorizontalLayout()
                else:
                    outer = VerticalLayout()
                outer.setSizeUndefined()

            inner = outer

            row = -1
            label_alignment = 0

        # Process each Item in the list:
        col = -1
        for item in content:

            # Keep a track of the current logical row and column unless the
            # layout is not a grid.
            col += 1
            if row >= 0 and col >= columns:
                col = 0
                row += 1

            # Get the name in order to determine its type:
            name = item.name

            # Check if is a label:
            if name == '':
                label = item.label
                if label != "":

                    # Create the label widget.
                    if item.style == 'simple':
                        label = Label(label)
                    else:
                        label = heading_text(None, text=label).control

                    self._add_widget(inner, label, row, col, show_labels)

                    if item.emphasized:
                        self._add_emphasis(label)

                # Continue on to the next Item in the list:
                continue

            # Check if it is a separator:
            if name == '_':
                cols = columns

                # See if the layout is a grid.
                if row >= 0:
                    # Move to the start of the next row if necessary.
                    if col > 0:
                        col = 0
                        row += 1

#                    # Skip the row we are about to do.
#                    row += 1

                    # Allow for the columns.
                    if show_labels:
                        cols *= 2

                for i in range(cols):
                    if self.horizontal:
                        # Add a vertical separator:
                        line = Panel()
                        line.setWidth('2px')
                        line.setHeight('-1px')
                        if row < 0:
                            inner.addComponent(line)
                        else:
                            inner.addComponent(line, row, i)
                    else:
                        # Add a horizontal separator:
                        line = Label('<hr />', Label.CONTENT_XHTML)
                        line.setWidth('100%')  # FIXME: explicit container size
                        if row < 0:
                            inner.addComponent(line)
                        else:
                            inner.addComponent(line, i, row)

                # Continue on to the next Item in the list:
                continue

            # Convert a blank to a 5 pixel spacer:
            if name == ' ':
                name = '5'

            # Check if it is a spacer:
            if all_digits.match( name ):

                # If so, add the appropriate amount of space to the layout:
                spacer = Label('')
                if self.horizontal:
                    # Add a horizontal spacer:
                    spacer.setWidth(name + 'px')
                else:
                    # Add a vertical spacer:
                    spacer.setHeight(name + 'px')

                self._add_widget(inner, spacer, row, col, show_labels)

                # Continue on to the next Item in the list:
                continue

            # Otherwise, it must be a trait Item:
            object      = eval( item.object_, globals(), ui.context )
            trait       = object.base_trait( name )
            desc        = trait.desc or ''
            fixed_width = False

            # Handle any label.
            if item.show_label:
                label = self._create_label(item, ui, desc)
                self._add_widget(inner, label, row, col, show_labels,
                                 label_alignment)
            else:
                label = None

            # Get the editor factory associated with the Item:
            editor_factory = item.editor
            if editor_factory is None:
                editor_factory = trait.get_editor()

                # If still no editor factory found, use a default text editor:
                if editor_factory is None:
                    from text_editor import ToolkitEditorFactory
                    editor_factory = ToolkitEditorFactory()

                # If the item has formatting traits set them in the editor
                # factory:
                if item.format_func is not None:
                    editor_factory.format_func = item.format_func

                if item.format_str != '':
                    editor_factory.format_str = item.format_str

                # If the item has an invalid state extended trait name, set it
                # in the editor factory:
                if item.invalid != '':
                    editor_factory.invalid = item.invalid

            # Create the requested type of editor from the editor factory:
            factory_method = getattr( editor_factory, item.style + '_editor' )
            editor         = factory_method( ui, object, name, item.tooltip,
                                        None).set(
                                 item        = item,
                                 object_name = item.object )

            # Tell the editor to actually build the editing widget.  Note that
            # "inner" is a layout.  This shouldn't matter as individual editors
            # shouldn't be using it as a parent anyway.  The important thing is
            # that it is not None (otherwise the main TraitsUI code can change
            # the "kind" of the created UI object).
            editor.prepare(inner)
            control = editor.control

            # Set the initial 'enabled' state of the editor from the factory:
            editor.enabled = editor_factory.enabled

            # Add emphasis to the editor control if requested:
            if item.emphasized:
                self._add_emphasis(control)

            # Give the editor focus if it requested it:
            if item.has_focus:
                control.focus()

            # Set the correct size on the control, as specified by the user:
            stretch = 0
            scrollable = editor.scrollable
            item_width = item.width
            item_height = item.height
            if (item_width != -1) or (item_height != -1):
                is_horizontal = self.horizontal

                min_size = control.minimumSizeHint()
                width = min_size.width()
                height = min_size.height()

                if (0.0 < item_width <= 1.0) and is_horizontal:
                    stretch = int(100 * item_width)

                item_width = int(item_width)
                if item_width < -1:
                    item_width  = -item_width
                else:
                    item_width = max(item_width, width)

                if (0.0 < item_height <= 1.0) and (not is_horizontal):
                    stretch = int(100 * item_height)

                item_height = int(item_height)
                if item_height < -1:
                    item_height = -item_height
                else:
                    item_height = max(item_height, height)

                control.setWidth(max(item_width, 0))
                control.setHeight(max(item_height, 0))

            # Bind the editor into the UIInfo object name space so it can be
            # referred to by a Handler while the user interface is active:
            Id = item.id or name
            info.bind( Id, editor, item.id )

            # Also, add the editors to the list of editors used to construct
            # the user interface:
            ui._editors.append( editor )

            # If the handler wants to be notified when the editor is created,
            # add it to the list of methods to be called when the UI is
            # complete:
            defined = getattr( handler, Id + '_defined', None )
            if defined is not None:
                ui.add_defined( defined )

            # If the editor is conditionally visible, add the visibility
            # 'expression' and the editor to the UI object's list of monitored
            # objects:
            if item.visible_when != '':
                ui.add_visible( item.visible_when, editor )

            # If the editor is conditionally enabled, add the enabling
            # 'expression' and the editor to the UI object's list of monitored
            # objects:
            if item.enabled_when != '':
                ui.add_enabled( item.enabled_when, editor )

            # Add the created editor control to the layout with the appropriate
            # size and stretch policies:
            ui._scrollable |= scrollable
#            item_resizable  = ((item.resizable is True) or
#                               ((item.resizable is Undefined) and scrollable))
#            if item_resizable:
#                stretch = stretch or 50
#                self.resizable = True
#            elif item.springy:
#                stretch = stretch or 50
#            policy = control.sizePolicy()
#            if self.horizontal:
#                policy.setHorizontalStretch(stretch)
#                if item_resizable or item.springy:
#                    policy.setHorizontalPolicy(QtGui.QSizePolicy.Expanding)
#            else:
#                policy.setVerticalStretch(stretch)
#                if item_resizable or item.springy:
#                    policy.setVerticalPolicy(QtGui.QSizePolicy.Expanding)
#            control.setSizePolicy(policy)

            # FIXME: Need to decide what to do about border_size and padding
            self._add_widget(inner, control, row, col, show_labels)

            # Save the reference to the label control (if any) in the editor:
            editor.label_control = label

        return outer