Source code for schrodinger.ui.qt.standard.colors
# defined by WCAG 2.0
# https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html
CONTRAST_THRESHOLD = 4.5
[docs]class NativeColors:
BLACK = '#000000'
GRAY = '#808080'
GREEN = '#00ff00'
ORANGE = '#ffa500'
RED = '#ff0000'
WHITE = '#ffffff'
[docs]class LightModeColors(NativeColors):
INVALID_STATE_BORDER = NativeColors.RED
STANDARD_BACKGROUND = NativeColors.WHITE
STANDARD_BORDER = NativeColors.WHITE
LINK = '#2e9cdc'
LINK_HOVERED = '#34b0f8'
LINK_DISABLED = '#acb8bf'
LINK_PRESSED = '#2e9cdc'
EMPHASIZED_TEXT = '#555555'
ERROR_TEXT = '#cc0000'
HEADER_TEXT = '#666666'
GOOD_TEXT = '#336622'
INFORMATIONAL_TEXT = '#666666'
LONG_ERROR_TEXT = '#990000'
STANDARD_TEXT = NativeColors.BLACK
SUCCESS_TEXT = '#006633'
WARNING_TEXT = '#c87c00'
DISABLED_BUTTON_BACKGROUND = '#cccccc'
DISABLED_BUTTON_COLOR = '#eeeeee'
DISABLED_BUTTON_BORDER = '#cccccc'
HIGHLIGHTED_BUTTON_BACKGROUND = 'qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #96b260, stop:1 #87a056)'
HIGHLIGHTED_BUTTON_BORDER_DISABLED = '#bbbbbb'
HIGHLIGHTED_BUTTON_BORDER_ENABLED = '#989898'
HIGHLIGHTED_BUTTON_COLOR = NativeColors.WHITE
HIGHLIGHTED_PRESSED_BUTTON_BACKGROUND_COLOR = '#87a056'
STANDARD_BUTTON_BACKGROUND = 'qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #dddddd, stop:1 #cccccc)'
STANDARD_BUTTON_BORDER_DISABLED = '#bbbbbb'
STANDARD_BUTTON_BORDER_ENABLED = '#989898'
STANDARD_BUTTON_COLOR = NativeColors.BLACK
STANDARD_PRESSED_BUTTON_BACKGROUND_COLOR = '#aaaaaa'
PRESSED_BUTTON_COLOR = NativeColors.WHITE
[docs]class DarkModeColors(NativeColors):
LINK = '#34b0f8'
LINK_HOVERED = '#2e9cdc'
LINK_DISABLED = '#798084'
LINK_PRESSED = '#34b0f8'
def _convert_color_comp(color_comp):
color_comp /= 255
if color_comp < 0.03928:
return color_comp / 12.92
return ((color_comp + 0.055) / 1.055)**2.4
[docs]def get_luma(rgb):
"""
Return the WCAG2 luma value of the given color.
See
https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
for additional information.
:param rgb: Red, green, blue values (range 0-255). Rgba values are allowed
but alpha is ignored.
:type rgb: tuple[int] or QtGui.QColor
:return: Luma value (range 0.0 - 1.0)
:rtype: float
"""
try:
rgb = rgb.getRgb()
except AttributeError:
pass
rgb = rgb[:3] # allow rgba 4-tuple
r, g, b = (_convert_color_comp(c) for c in rgb)
return r * 0.2126 + g * 0.7152 + b * 0.0722
[docs]def get_contrast(rgb1, rgb2):
"""
Return the contrast ratio for the given colors.
See
https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html#contrast-ratiodef
for additional information.
:return: Contrast ratio (range 1.0 - 21.0)
:rtype: float
"""
epsilon = 0.05
contrast = (get_luma(rgb1) + epsilon) / (get_luma(rgb2) + epsilon)
if contrast < 1:
contrast = 1 / contrast
return contrast
[docs]def get_contrasting_color(set_rgb, contrast=CONTRAST_THRESHOLD, options=None):
"""
:param set_rgb: Red, green, blue values (range 0-255). Rgba values are allowed
but alpha is ignored.
:type set_rgb: tuple[int] or QtGui.QColor
:param contrast: Contrast ratio (range 1.0 - 21.0)
:type contrast: float
:param options: Possible colors to contrast with `set_rgb`
:type options: iterable(tuple[int] or QtGui.QColor)
"""
try:
set_rgb = set_rgb.getRgb()
except AttributeError:
pass
if options:
# Check whether any option has sufficient contrast
contrasts = [get_contrast(rgb, set_rgb) for rgb in options]
best_contrast = max(contrasts)
if best_contrast >= contrast:
idx = contrasts.index(best_contrast)
return options[idx]
# Otherwise, return most contrasting default color
default_options = [(0, 0, 0), (255, 255, 255)]
contrasts = [get_contrast(rgb, set_rgb) for rgb in default_options]
best_contrast = max(contrasts)
idx = contrasts.index(best_contrast)
return default_options[idx]
[docs]def is_color_dark(rgb):
"""
For a given color, return whether it is dark. If a background color is
dark, it should have a light foreground color and vice versa.
:note: This is determined using the luma value of the given color. The
function returns True if the luma is less than 50% (i.e. closer to
black than white) and False if the luma is greater than 50% (i.e.
closer to white than black).
:param rgb: Red, green, blue values (range 0-255). Rgba values are allowed
but alpha is ignored.
:type rgb: tuple[int]
:return: Whether the color is dark
:rtype: bool
"""
return get_luma(rgb) < 0.5