"""
Contains helpers for creating layouts.
Copyright Schrodinger, LLC. All rights reserved.
"""
#- Imports -------------------------------------------------------------------
from schrodinger.Qt import QtWidgets
#- Globals -------------------------------------------------------------------
STRETCH = 0
ROW_SPAN = 1
COL_SPAN = 2
#- Functions -----------------------------------------------------------------
def _add_to_layout(obj, layout, *args, **kwargs):
    """
    Cycles through adding to a layout. First it tries to add the
    `obj` as a widget, then as an item and finally as a layout.
    """
    try:
        layout.addWidget(obj, *args, **kwargs)
    except TypeError:
        try:
            layout.addItem(obj, *args, **kwargs)
        except TypeError:
            # If an error occurs here let QT raise the error
            layout.addLayout(obj, *args, **kwargs)
def _apply_box_settings(layout, objects, margins=None, spacing=5):
    """
    Private function to apply common settings to a `QtWidgets.QHBoxLayout`
    or `QtWidgets.QVBoxLayout` object.
    :param objects: Objects (widget, item, layout) to add
    :type objects: mixed (list or single object)
    :param stretch: Whether or not to add a stretch to the end of the layout
    :type stretch: bool
    :param margins: Margins used in `QtWidgets.QHBoxLayout.setContentsMargins`
    :type margins: tuple
    """
    if not isinstance(objects, (list, tuple)):
        objects = [objects]
    margins = margins or (-1, -1, -1, -1)
    layout.setSpacing(spacing)
    layout.setContentsMargins(*margins)
    for obj in objects:
        if obj == STRETCH:
            layout.addStretch()
        else:
            _add_to_layout(obj, layout)
    return layout
[docs]def vbox(objects, margins=None, spacing=5):
    """
    Function used to create a `QtWidgets.QVBoxLayout` object.
    :param objects: Objects (widget, item, layout) to add
    :type objects: mixed (list or single object)
    :param margins: Margins used in `QtWidgets.QHBoxLayout.setContentsMargins`
    :type margins: tuple
    """
    layout = QtWidgets.QVBoxLayout()
    hbox_layout = _apply_box_settings(layout, objects, margins, spacing)
    return hbox_layout 
[docs]def hbox(objects, margins=None, spacing=5):
    """
    Function used to create a `QtWidgets.QHBoxLayout` object.
    :param objects: Objects (widget, item, layout) to add
    :type objects: mixed (list or single object)
    :param margins: Margins used in `QtWidgets.QHBoxLayout.setContentsMargins`
    :type margins: tuple
    """
    layout = QtWidgets.QHBoxLayout()
    hbox_layout = _apply_box_settings(layout, objects, margins, spacing)
    return hbox_layout 
[docs]def grid(objects, stretch=False, margins=None, hspace=5, vspace=5):
    """
    Function used to create a `QtWidgets.QGridLayout` object. The `objects`
    is a list of objects that will populate the grid. The grid's row
    count will equal the length of `objects` and it's column count will
    equal the length of the row with the most items. If you want to skip
    a column, set it to `None`, and if you want a column to span multiple
    columns add a `schrodinger.application.bioluminate.layout.ROW_SPAN`
    to all the preceding columns you want it to occupy.
    Example::
        `objects = [
            [ layout.ROW_SPAN, layout.ROW_SPAN, label, None, line_edit],
            [ double_spinner,  push_button, line_edit ]
          ]
          grid = layout.grid(objects)
        `
    The above will return a grid layout like::
        --------------------------------------------------------------
        |                 label                    |   |  line_edit  |
        -------------------------------------------------------------
        | double_spinner | push_button | line_edit |   |             |
        --------------------------------------------------------------
    :param objects: Objects (widget, item, or layout) to add to a single
                    `QtWidgets.QGridLayout`
    :type objects: list of lists
    """
    margins = margins or (-1, -1, -1, -1)
    grid_layout = QtWidgets.QGridLayout()
    # Set the columns up so that blank columns still take space up.
    # This keeps the layout much cleaner if objects are dynamic
    col_lens = [len(a) for a in objects]
    #for i in range(0,max(col_lens)):
    #    grid_layout.setColumnMinimumWidth(i, 50)
    grid_layout.setHorizontalSpacing(hspace)
    grid_layout.setVerticalSpacing(vspace)
    grid_layout.setContentsMargins(*margins)
    for i, row in enumerate(objects):
        row_span = 1
        # We do not support column spans yet but we still need to add
        # the variable for when we call _add_to_layout
        col_span = 1
        for j, wid in enumerate(row):
            if wid is None:
                continue
            if wid == ROW_SPAN:
                row_span += 1
                continue
            j -= (row_span - 1)
            _add_to_layout(wid, grid_layout, i, j, row_span, col_span)
            row_span = 1
            col_span = 1
    return grid_layout