Source code for bokeh.core.property.color

#-----------------------------------------------------------------------------
# Copyright (c) 2012 - 2020, Anaconda, Inc., and Bokeh Contributors.
# All rights reserved.
#
# The full license is in the file LICENSE.txt, distributed with this software.
#-----------------------------------------------------------------------------
''' Provide color related properties.

'''

#-----------------------------------------------------------------------------
# Boilerplate
#-----------------------------------------------------------------------------
import logging # isort:skip
log = logging.getLogger(__name__)

#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------

# Standard library imports
import re

# Bokeh imports
from ... import colors
from .. import enums
from .bases import Property
from .container import Tuple
from .either import Either
from .enum import Enum
from .numeric import Byte, Percent
from .string import Regex

#-----------------------------------------------------------------------------
# Globals and constants
#-----------------------------------------------------------------------------

__all__ = (
    'Color',
    'RGB',
    'ColorHex',
)

#-----------------------------------------------------------------------------
# General API
#-----------------------------------------------------------------------------


[docs]class RGB(Property): ''' Accept colors.RGB values. ''' def validate(self, value, detail=True): super().validate(value, detail) if not (value is None or isinstance(value, colors.RGB)): msg = "" if not detail else "expected RGB value, got %r" % (value,) raise ValueError(msg)
[docs]class Color(Either): ''' Accept color values in a variety of ways. For colors, because we support named colors and hex values prefaced with a "#", when we are handed a string value, there is a little interpretation: if the value is one of the 147 SVG named colors or it starts with a "#", then it is interpreted as a value. If a 3-tuple is provided, then it is treated as an RGB (0..255). If a 4-tuple is provided, then it is treated as an RGBa (0..255), with alpha as a float between 0 and 1. (This follows the HTML5 Canvas API.) Example: .. code-block:: python >>> class ColorModel(HasProps): ... prop = Color() ... >>> m = ColorModel() >>> m.prop = "firebrick" >>> m.prop = "#a240a2" >>> m.prop = (100, 100, 255) >>> m.prop = (100, 100, 255, 0.5) >>> m.prop = "junk" # ValueError !! >>> m.prop = (100.2, 57.3, 10.2) # ValueError !! ''' def __init__(self, default=None, help=None): types = (Enum(enums.NamedColor), Regex(r"^#[0-9a-fA-F]{6}$"), Regex(r"^rgba\(((25[0-5]|2[0-4]\d|1\d{1,2}|\d\d?)\s*," r"\s*?){2}(25[0-5]|2[0-4]\d|1\d{1,2}|\d\d?)\s*," r"\s*([01]\.?\d*?)\)"), Regex(r"^rgb\(((25[0-5]|2[0-4]\d|1\d{1,2}|\d\d?)\s*," r"\s*?){2}(25[0-5]|2[0-4]\d|1\d{1,2}|\d\d?)\s*?\)"), Tuple(Byte, Byte, Byte), Tuple(Byte, Byte, Byte, Percent), RGB) super().__init__(*types, default=default, help=help) def __str__(self): return self.__class__.__name__ def transform(self, value): if isinstance(value, tuple): value = colors.RGB(*value).to_css() return value def _sphinx_type(self): return self._sphinx_prop_link()
class ColorHex(Color): ''' ref Color The only difference with Color is it's transform in hexadecimal string when send to javascript side ''' def transform(self, value): if isinstance(value, str): value = value.lower() if value.startswith('rgb'): value = colors.RGB(*[int(val) for val in re.findall(r"\d+", value)[:3]]).to_hex() elif value in enums.NamedColor: value = getattr(colors.named, value).to_hex() elif isinstance(value, tuple): value = colors.RGB(*value).to_hex() else: value = value.to_hex() return value.lower() #----------------------------------------------------------------------------- # Dev API #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # Private API #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # Code #-----------------------------------------------------------------------------