Source code for schrodinger.ui.qt.standard_widgets.buttons

"""
Module containing classes for buttons styled for use in Schrodinger panels.
"""

from schrodinger.Qt import QtWidgets
from schrodinger.ui.qt.standard.colors import LightModeColors
import enum


def apply_style_sheet_to_button(button, style):
    """
    Apply a Schrodinger color scheme CSS to the given QPushButton object.

    :param button: Button to apply the styling to.
    :type button: QtWidgets.QPushButton

    :param style: Style to use
    :type style: `StyledButton.Style`
    """
    background_gradient = LightModeColors.STANDARD_BUTTON_BACKGROUND
    pressed_bg_color = LightModeColors.STANDARD_PRESSED_BUTTON_BACKGROUND_COLOR

    if style == StyledButton.Style.Highlighted:
        background_gradient = LightModeColors.HIGHLIGHTED_BUTTON_BACKGROUND
        pressed_bg_color = LightModeColors.HIGHLIGHTED_PRESSED_BUTTON_BACKGROUND_COLOR
        text_color = LightModeColors.HIGHLIGHTED_BUTTON_COLOR
    elif style == StyledButton.Style.HighlightedText:
        text_color = LightModeColors.GOOD_TEXT
    else:
        if style != StyledButton.Style.Standard:
            raise ValueError('Invalid style specified')
        text_color = LightModeColors.STANDARD_BUTTON_COLOR

    css = f'''
    QPushButton {{
      padding: -5px 20px; /* spacing WITHIN; make button shorter & wider */
      margin: 0px 3px; /* spacing between buttons */
      height: 28px;
      color: {text_color};
      background-color: {background_gradient};
      border-radius: 2px;
      border: 1px solid {LightModeColors.STANDARD_BUTTON_BORDER_ENABLED};
    }}
    QPushButton:!enabled {{
      color: {LightModeColors.DISABLED_BUTTON_COLOR};
      background-color: {LightModeColors.DISABLED_BUTTON_BACKGROUND};
      border: 1px solid {LightModeColors.DISABLED_BUTTON_BORDER}
    }}
    QPushButton:pressed {{
      color: {LightModeColors.PRESSED_BUTTON_COLOR};
      background-color: {pressed_bg_color};
    }}
    '''

    button.setStyleSheet(css)


class StyledButton(QtWidgets.QPushButton):
    """
    A QPushButton that uses custom CSS, and offers ability to be "highlighted"
    with a green background (e.g. for Run buttons).
    """

    class Style(enum.Enum):
        # Standard button - gray background, black text
        Standard = 'Standard'  # gray background, black text
        # Green background, white text - similar to "defualt" button, except
        # that "Enter" key is not mapped to it.
        Highlighted = 'Highlighted'
        # Standard button with green text:
        HighlightedText = 'HighlightedText'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._style = self.Style.Standard
        self.updateStyleSheet()

    def setStyle(self, style):
        """
        Set the style of the button to one of available styles.

        :param style: Style to use.
        :type stle: `StyledButton.Style`
        """
        self._style = style
        self.updateStyleSheet()

    def setHighlighted(self, highlighted):
        """
        Whether to make the button background green, to make the button "jump
        out" to the user as the next likely action to take. Similar to a
        "default" button state (often used in dialog boxes), except that it
        doesn't activate on pressing of the "Enter" key.
        """
        self._style = self.Style.Highlighted if highlighted else self.Style.Standard
        self.updateStyleSheet()

    def updateStyleSheet(self):
        apply_style_sheet_to_button(self, self._style)


class FlatButton(QtWidgets.QToolButton):
    """
    A flat icon toolbutton. To use this, it's necessary to call setIconPath
    with the appropriate path to get the icon to show up. If a different icon
    is to be used for hover/pressed states, call setHoverIconPath. The size
    of the icon can be specified using setIconSize_ (there is already a Qt
    setIconSize method on the class)
    """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._normal_path = ""
        self._hover_path = ""
        self._disabled_path = ""
        self._pressed_path = ""
        self._icon_width = 20
        self._icon_height = 20
        self.updateStyleSheet()

    def setIconPath(self, normal_path):
        self._normal_path = normal_path
        self.updateStyleSheet()

    def setHoverIconPath(self, hover_path):
        self._hover_path = hover_path
        self.updateStyleSheet()

    def setDisabledIconPath(self, disabled_path):
        self._disabled_path = disabled_path
        self.updateStyleSheet()

    def setPressedIconPath(self, pressed_path):
        self._pressed_path = pressed_path
        self.updateStyleSheet()

    def setIconSize_(self, width=None, height=None):
        if width:
            self._icon_width = width
        if height:
            self._icon_height = height
        self.updateStyleSheet()

    def updateStyleSheet(self):
        ss = """
        QToolButton {
            width: """ + str(self._icon_width) + """px;
            height: """ + str(self._icon_height) + """px;
            border: 1px solid transparent;
            background: none;
            padding: 0px 0px 0px 0px;
        }"""
        if self._normal_path:
            ss += """
        QToolButton {
            image: url(""" + self._normal_path + """);
        }"""
        if self._hover_path:
            ss += """
        QToolButton:hover,
        QToolButton:pressed {
            image: url(""" + self._hover_path + """);
        }"""
        if self._disabled_path:
            ss += """
        QToolButton:disabled {
            image: url(""" + self._disabled_path + """);
        }"""
        if self._pressed_path:
            ss += """
        QToolButton:pressed {
            image: url(""" + self._pressed_path + """);
        }"""
        self.setStyleSheet(ss)