Source code for highcharts_core.options.chart

import os
from typing import Optional, List
from decimal import Decimal

from validator_collection import validators, checkers

from highcharts_core import errors, constants, utility_functions
from highcharts_core.decorators import class_sensitive, validate_types
from highcharts_core.metaclasses import HighchartsMeta
from highcharts_core.utility_classes.javascript_functions import CallbackFunction
from highcharts_core.utility_classes.animation import AnimationOptions
from highcharts_core.utility_classes.gradients import Gradient
from highcharts_core.utility_classes.patterns import Pattern
from highcharts_core.utility_classes.shadows import ShadowOptions
from highcharts_core.utility_classes.events import ChartEvents
from highcharts_core.options.chart.options_3d import Options3D
from highcharts_core.options.axes.parallel_axes import ParallelAxesOptions
from highcharts_core.options.chart.scrollable_plot_area import ScrollablePlotArea
from highcharts_core.options.chart.zooming import ZoomingOptions


[docs]class PanningOptions(HighchartsMeta): """Configures panning behavior in a chart. .. hint:: Best used with :meth:`Chart.pan_key` to combine zooming and panning. .. note:: On touch devices, when the :meth:`Tooltip.follow_touch_move` property is ``True`` (default), panning requires two fingers. To allow panning with one finger, set ``follow_touch_move`` to ``False``. """ def __init__(self, **kwargs): self._enabled = None self._type = None self.enabled = kwargs.get('enabled', None) self.type = kwargs.get('type', None) @property def enabled(self) -> Optional[bool]: """If ``True``, enables chart panning. Defaults to ``False``. :returns: Flag enabling or disabling chart panning. :rtype: :class:`bool <python:bool>` or :obj:`None <python:None>` """ return self._enabled @enabled.setter def enabled(self, value): if value is None: self._enabled = None else: self._enabled = bool(value) @property def type(self) -> Optional[str]: """Determines in what dimensions the user can pan the chart. Defaults to ``'x'``. Accepts: * ``'x'`` * ``'y'`` * ``'xy'`` :rtype: :class:`str` or :obj:`None <python:None>` """ return self._type @type.setter def type(self, value): if not value: self._type = None else: value = validators.string(value) value = value.lower() if value not in ['x', 'y', 'xy']: raise errors.HighchartsValueError(f'Panning.type expects a value of ' f'either "x", "y", "xy", or None. ' f'Received: {value}') self._type = value @classmethod def _get_kwargs_from_dict(cls, as_dict): kwargs = { 'enabled': as_dict.get('enabled', None), 'type': as_dict.get('type', None) } return kwargs def _to_untrimmed_dict(self, in_cls = None) -> dict: return { 'enabled': self.enabled, 'type': self.type }
[docs]class ChartOptions(HighchartsMeta): """Configuration settings that apply to a chart.""" def __init__(self, **kwargs): self._align_thresholds = None self._align_ticks = None self._allow_mutating_data = None self._animation = None self._axis_layout_runs = None self._background_color = None self._border_color = None self._border_radius = None self._border_width = None self._class_name = None self._color_count = None self._display_errors = None self._events = None self._height = None self._ignore_hidden_series = None self._inverted = None self._margin_bottom = None self._margin_left = None self._margin_right = None self._margin_top = None self._number_formatter = None self._options_3d = None self._pan_key = None self._panning = None self._parallel_axes = None self._parallel_coordinates = None self._plot_background_color = None self._plot_background_image = None self._plot_border_color = None self._plot_border_width = None self._plot_shadow = None self._polar = None self._reflow = None self._render_to = None self._scrollable_plot_area = None self._selection_marker_fill = None self._shadow = None self._show_axes = None self._spacing_bottom = None self._spacing_left = None self._spacing_top = None self._spacing_right = None self._style = None self._styled_mode = None self._type = None self._width = None self._zooming = None self.align_thresholds = kwargs.get('align_thresholds', None) self.align_ticks = kwargs.get('align_ticks', None) self.allow_mutating_data = kwargs.get('allow_mutating_data', None) self.animation = kwargs.get('animation', None) self.axis_layout_runs = kwargs.get('axis_layout_runs', None) self.background_color = kwargs.get('background_color', None) self.border_color = kwargs.get('border_color', None) self.border_radius = kwargs.get('border_radius', None) self.border_width = kwargs.get('border_width', None) self.class_name = kwargs.get('class_name', None) self.color_count = kwargs.get('color_count', None) self.display_errors = kwargs.get('display_errors', None) self.events = kwargs.get('events', None) self.height = kwargs.get('height', None) self.ignore_hidden_series = kwargs.get('ignore_hidden_series', None) self.inverted = kwargs.get('inverted', None) self.margin = kwargs.get('margin', None) if not kwargs.get('margin', None): self.margin_bottom = kwargs.get('margin_bottom', None) self.margin_left = kwargs.get('margin_left', None) self.margin_right = kwargs.get('margin_right', None) self.margin_top = kwargs.get('margin_top', None) self.number_formatter = kwargs.get('number_formatter', None) self.options_3d = kwargs.get('options_3d', None) self.pan_key = kwargs.get('pan_key', None) self.panning = kwargs.get('panning', None) self.parallel_axes = kwargs.get('parallel_axes', None) self.parallel_coordinates = kwargs.get('parallel_coordinates', None) self.plot_background_color = kwargs.get('plot_background_color', None) self.plot_background_image = kwargs.get('plot_background_image', None) self.plot_border_color = kwargs.get('plot_border_color', None) self.plot_border_width = kwargs.get('plot_border_width', None) self.plot_shadow = kwargs.get('plot_shadow', None) self.polar = kwargs.get('polar', None) self.reflow = kwargs.get('reflow', None) self.render_to = kwargs.get('render_to', None) self.scrollable_plot_area = kwargs.get('scrollable_plot_area', None) self.selection_marker_fill = kwargs.get('selection_marker_fill', None) self.shadow = kwargs.get('shadow', None) self.show_axes = kwargs.get('show_axes', None) self.spacing = kwargs.get('spacing', None) if not kwargs.get('spacing', None): self.spacing_bottom = kwargs.get('spacing_bottom', None) self.spacing_left = kwargs.get('spacing_left', None) self.spacing_top = kwargs.get('spacing_top', None) self.spacing_right = kwargs.get('spacing_right', None) self.style = kwargs.get('style', None) self.styled_mode = kwargs.get('styled_mode', None) self.type = kwargs.get('type', None) self.width = kwargs.get('width', None) self.zooming = kwargs.get('zooming', None) @property def _dot_path(self) -> Optional[str]: """The dot-notation path to the options key for the current class. :rtype: :class:`str <python:str>` or :obj:`None <python:None>` """ return 'chart' @property def align_thresholds(self) -> Optional[bool]: """When using multiple axes, align the thresholds. When ``True``, other ticks will also be aligned. Defaults to ``False``. .. note:: For line series and some other series types, the threshold option is set to ``null`` by default. This will in turn cause their y-axis to not have a threshold. In order to avoid that, set the series threshold to ``0`` or another number. .. note:: If :meth:`AxisOptions.start_on_tick` or :meth:`AxisOptions.end_on_tick` are set to ``False``, or if the axis is logarithmic, the threshold will not be aligned. :returns: Flag indicating whether thresholds should be aligned. :rtype: :class:`bool <python:bool>` or :obj:`None <python:None>` """ return self._align_thresholds @align_thresholds.setter def align_thresholds(self, value): if value is None: self._align_thresholds = None else: self._align_thresholds = bool(value) @property def align_ticks(self) -> Optional[bool]: """If ``True`` and using multiple axes, the ticks of two or more opposite axes will automatically be aligned by adding ticks to the axis or axes with the least ticks, as if ``tick_amount`` were specified. This can be prevented by setting ``align_ticks`` to ``False``. Defaults to ``True``. .. hint:: If the grid lines look messy, it's a good idea to hide them for the secondary axis by setting ``grid_line_width`` to ``0``. .. warning:: If ``start_on_tick`` or ``end_on_tick`` in the axis options are set to ``False``, then tick alignment will be disabled for the axis. .. warning:: Aways disabled for logarithmic axes. :returns: Flag indicating whether ot align ticks along the axes. :rtype: :class:`bool <python:bool>` or :obj:`None <python:None>` """ return self._align_ticks @align_ticks.setter def align_ticks(self, value): if value is None: self._align_ticks = None else: self._align_ticks = bool(value) @property def allow_mutating_data(self) -> Optional[bool]: """If ``True``, the original data source will be allowed to be mutated. However, if ``False`` then Highcharts will create a copy of the original data to prevent inadvertent mutation. Defaults to ``True``. .. note:: By default, (for memory and performance reasons) the chart does not copy the data but keeps it as a reference. In some cases, this might result in mutating the original data source. In order to prevent that, set this property to ``False``. Please note that changing this may decrease performance, especially with bigger sets of data. :returns: Flag indicating whether to allow mutation by referencing th eoriginal data (``True``), or prevent it by copying the original data (``False``). :rtype: :class:`bool <python:bool>` or :obj:`None <python:None>` """ return self._allow_mutating_data @allow_mutating_data.setter def allow_mutating_data(self, value): if value is None: self._allow_mutating_data = None else: self._allow_mutating_data = bool(value) @property def animation(self) -> Optional[bool | AnimationOptions]: """Configures the overall animation for all chart updating. The animation can be configured as either a boolean or a :class:`AnimationOptions` object. If ``True``, it will apply the ``'swing'`` jQuery easing and a duration of 500 ms by default. If used as a :class:`AnimationOptions` instance, you have more fine-grianed configuration control. Animation can be disabled throughout the chart by setting it to ``False`` here. It can be overridden for each individual API method as a function parameter. The only animation not affected by this option is the initial series animation, see :meth:`PlotOptions.series.animation`. When zooming on a series with less than 100 points, the chart redraw will be done with animation, but in case of more data points, it is necessary to set this option to ensure animation on zoom. :returns: Settings for the animation of image patterns. :rtype: :class:`AnimationOptions` or :obj:`None <python:None>` """ return self._animation @animation.setter def animation(self, value): if value is None: self._animation = None elif value is False: self._animation = False elif value is True: self._animation = True else: self._animation = validate_types(value, types = AnimationOptions) @property def axis_layout_runs(self) -> Optional[int]: """The number of axis layout runs to execute when rendering the chart. Defaults to ``2``. .. note:: When a chart with an x and a y-axis is rendered, we first pre-render the labels of both in order to measure them. Then, if either of the axis labels take up so much space that it significantly affects the length of the other axis, we repeat the process. By default we stop at two axis layout runs, but it may be that the second run also alters the space required by either axis, for example if it causes the labels to rotate. In this situation, a subsequent redraw of the chart may cause the tick and label placement to change for apparently no reason. Use the ``.axis_layout_runs`` property to set the maximum allowed number of repetitions. .. warning:: Keep in mind that the default value of ``2`` is set because every run costs performance time. Changing this value option to higher than the default might decrease performance significantly, especially with bigger sets of data. :returns: The maximum allowed number of axis layout runs. :rtype: :class:`int <python:int>` """ return self._axis_layout_runs @axis_layout_runs.setter def axis_layout_runs(self, value): self._axis_layout_runs = validators.integer(value, allow_empty = True) @property def background_color(self) -> Optional[str | Gradient | Pattern]: """The background color or gradient for the outer chart area. Defaults to ``'#ffffff'``. :returns: The background color for the outer chart area. :rtype: :class:`str <python:str>`, :class:`Gradient`, :class:`Pattern``, or :obj:`None <python:None>` """ return self._background_color @background_color.setter def background_color(self, value): from highcharts_core import utility_functions self._background_color = utility_functions.validate_color(value) @property def border_color(self) -> Optional[str | Gradient | Pattern]: """The color of the outer chart border. Defaults to ``'#335cad'``. :returns: The color of the outer chart border. :rtype: :class:`str <python:str>`, :class:`Gradient`, :class:`Pattern``, or :obj:`None <python:None>` """ return self._border_color @border_color.setter def border_color(self, value): from highcharts_core import utility_functions self._border_color = utility_functions.validate_color(value) @property def border_radius(self) -> Optional[int | float | Decimal]: """The border radius (in pixels) applied to the outer chart border. Defaults to ``0``. :returns: The border radius to apply to the outer chart border. :rtype: numeric or :obj:`None <python:None>` """ return self._border_radius @border_radius.setter def border_radius(self, value): self._border_radius = validators.numeric(value, allow_empty = True) @property def border_width(self) -> Optional[int | float | Decimal]: """The border width (in pixels) applied to the outer chart border. Defaults to ``0``. :returns: The border width to apply to the outer chart border. :rtype: numeric or :obj:`None <python:None>` """ return self._border_width @border_width.setter def border_width(self, value): self._border_width = validators.numeric(value, allow_empty = True) @property def class_name(self) -> Optional[str]: """A classname to apply styling using CSS. :returns: The classname to apply to enable styling via CSS. :rtype: :class:`str <python:str>` or :obj:`None <python:None>` """ return self._class_name @class_name.setter def class_name(self, value): self._class_name = validators.string(value, allow_empty = True) @property def color_count(self) -> Optional[int]: """In styled mode, sets how many colors the class names should rotate between. Defaults to ``10`` With ten colors, series (or points) are given class names like ``highcharts-color-0``, ``highcharts-color-0`` [...] ``highcharts-color-9``. The equivalent in non-styled mode is to set colors using the colors setting. :returns: The number of colors to cycle through in styled mode. :rtype: :class:`int <python:int>` or :obj:`None <python:None>` """ return self._color_count @color_count.setter def color_count(self, value): self._color_count = validators.integer(value, allow_empty = True, minimum = 0, coerce_value = True) @property def display_errors(self) -> Optional[bool]: """If ``True``, will display errors on the chart itself. If ``False``, will only report errors to the console. Defaults to ``True``. :returns: Flag indicating whether ot display errors on the chart. :rtype: :class:`bool <python:bool>` or :obj:`None <python:None>` """ return self._display_errors @display_errors.setter def display_errors(self, value): if value is None: self._display_errors = None else: self._display_errors = bool(value) @property def events(self) -> Optional[ChartEvents]: """Definition of JavaScript event listeners to apply to the chart. :rtype: :class:`ChartEvents` or :obj:`None <python:None>` """ return self._events @events.setter @class_sensitive(ChartEvents) def events(self, value): self._events = value @property def height(self) -> Optional[constants.EnforcedNullType | int | float | Decimal | str]: """An explicit height for the chart. Defaults to :obj:`None <python:None>`. If a number, the height is given in pixels. If given a percentage string (for example ``'56%'``), the height is given as the percentage of the actual chart width. This allows for preserving the aspect ratio across responsive sizes. By default (when :obj:`None python:None>`) the height is calculated from the offset height of the containing element, or 400 pixels if the containing element's height is 0. :rtype: :class:`EnforcedNullType` or numeric or :class:`str <python:str>` or :obj:`None <python:None>` """ return self._height @height.setter def height(self, value): if value is None or isinstance(value, constants.EnforcedNullType): self._height = None else: try: try: self._height = validators.numeric(value, allow_empty = False, minimum = 0) except ValueError: self._height = validators.string(value, allow_empty = False) except ValueError: raise errors.HighchartsValueError('Unable to resolve value to a ' 'supported data type.') @property def ignore_hidden_series(self) -> Optional[bool]: """If ``True``, the axes will scale to the remaining visible series once one series is hidden. If ``False``, hiding and showing a series will not affect the axes or the other series. Defaults to ``True``. .. note:: For stacks, once one series within the stack is hidden, the rest of the stack will close in around it even if the axis is not affected. :returns: Flag indicating whether to ignore hidden series. :rtype: :class:`bool <python:bool>` or :obj:`None <python:None>` """ return self._ignore_hidden_series @ignore_hidden_series.setter def ignore_hidden_series(self, value): if value is None: self._ignore_hidden_series = None else: self._ignore_hidden_series = bool(value) @property def inverted(self) -> Optional[bool]: """If ``True``, inverts the axes so that the x-axis is vertical and y-axis is horizontal. Defaults to ``False``. .. hint:: When ``True``, the x-axis is reversed by default. .. warning:: If a bar series is present in the chart, it will be inverted automatically. .. hint:: Inverting the chart doesn't have an effect if there are no cartesian series in the chart, or if the chart is a polar chart type. :returns: Flag indicating whether to invert the axes. :rtype: :class:`bool <python:bool>` or :obj:`None <python:None>` """ return self._inverted @inverted.setter def inverted(self, value): if value is None: self._inverted = None else: self._inverted = bool(value) @property def margin(self) -> Optional[List[int | float | Decimal]]: """The margin between the outer edge of the chart and the plot area. The numbers in the array designate top, right, bottom and left respectively. By default there is no margin. The actual space is dynamically calculated from the offset of axis labels, axis title, title, subtitle and legend in addition to the ``spacing_top``, ``spacing_right``, ``spacing_bottom`` and ``spacing_left`` options. .. note:: This property is a convenience property to consolidate simple margin configuration across the ``margin_top``, ``margin_right``, ``margin_bottom``, and ``margin_left`` options. Values will be propagated between all options. :rtype: :class:`list <python:list>` of four numeric values or :obj:`None <python:None>` """ result = [self.margin_top, self.margin_right, self.margin_bottom, self.margin_left] if not any(result): return None return result @margin.setter def margin(self, value): if value is None: self.margin_top = None self.margin_right = None self.margin_bottom = None self.margin_left = None elif checkers.is_iterable(value): if len(value) != 4: raise errors.HighchartsValueError(f'margin expects either a single value ' f'or an iterable of four values. ' f'Received an iterable of {len(value)} ' f'values ({value})') if value[0] == 'null': self.margin_top = None else: self.margin_top = value[0] if value[1] == 'null': self.margin_right = None else: self.margin_right = value[1] if value[2] == 'null': self.margin_bottom = None else: self.margin_bottom = value[2] if value[3] == 'null': self.margin_left = None else: self.margin_left = value[3] else: self.margin_top = value self.margin_right = value self.margin_bottom = value self.margin_left = value @property def margin_bottom(self) -> Optional[int | float | Decimal]: """The margin between the bottom outer edge of the chart and the plot area. Use this to set a fixed pixel value for the margin as opposed to the default dynamic margin. By default, not set. .. seealso:: * :meth:`Chart.spacing_bottom` :rtype: numeric or :obj:`None <python:None>` """ return self._margin_bottom @margin_bottom.setter def margin_bottom(self, value): if value is None or isinstance(value, constants.EnforcedNullType): self._margin_bottom = None else: self._margin_bottom = validators.numeric(value) @property def margin_left(self) -> Optional[int | float | Decimal]: """The margin between the left outer edge of the chart and the plot area. Use this to set a fixed pixel value for the margin as opposed to the default dynamic margin. By default, not set. .. seealso:: * :meth:`Chart.spacing_left` :rtype: numeric or :obj:`None <python:None>` """ return self._margin_left @margin_left.setter def margin_left(self, value): if value is None or isinstance(value, constants.EnforcedNullType): self._margin_left = None else: self._margin_left = validators.numeric(value) @property def margin_right(self) -> Optional[int | float | Decimal]: """The margin between the right outer edge of the chart and the plot area. Use this to set a fixed pixel value for the margin as opposed to the default dynamic margin. By default, not set. .. seealso:: * :meth:`Chart.spacing_right` :rtype: numeric or :obj:`None <python:None>` """ return self._margin_right @margin_right.setter def margin_right(self, value): if value is None or isinstance(value, constants.EnforcedNullType): self._margin_right = None else: self._margin_right = validators.numeric(value) @property def margin_top(self) -> Optional[int | float | Decimal]: """The margin between the top outer edge of the chart and the plot area. Use this to set a fixed pixel value for the margin as opposed to the default dynamic margin. By default, not set. .. seealso:: * :meth:`Chart.spacing_top` :rtype: numeric or :obj:`None <python:None>` """ return self._margin_top @margin_top.setter def margin_top(self, value): if value is None or isinstance(value, constants.EnforcedNullType): self._margin_top = None else: self._margin_top = validators.numeric(value) @property def number_formatter(self) -> Optional[CallbackFunction]: """JavaScript Callback function to override the default function that formats all the numbers in the chart. Returns a string with the formatted number. :rtype: :class:`CallbackFunction` or :obj:`None <python:None>` """ return self._number_formatter @number_formatter.setter @class_sensitive(CallbackFunction) def number_formatter(self, value): self._number_formatter = value @property def options_3d(self) -> Optional[Options3D]: """Options to render charts in three dimensions. .. note:: This feature requires the JavaScript ``highcharts-3d.js`` module, found in the download package or online at `code.highcharts.com/highcharts-3d.js <https://code.highcharts.com/highcharts-3d.js>`_. :rtype: :class:`Options3D` or :obj:`None <python:None>` """ return self._options_3d @options_3d.setter @class_sensitive(Options3D) def options_3d(self, value): self._options_3d = value @property def pan_key(self) -> Optional[str]: """Allows setting a key to switch between zooming and panning. Accepts the following values: * ``'alt'`` * ``'ctrl'`` * ``'meta'`` (the command key on Mac and Windows key on Windows) * ``'shift'``. The keys are mapped directly to the key properties of the click event argument (``event.altKey``, ``event.ctrlKey``, ``event.metaKey``, and ``event.shiftKey``). :returns: The key that switches between zooming and panning. :rtype: :class:`str <python:str>` or :obj:`None <python:None>` """ return self._pan_key @pan_key.setter def pan_key(self, value): if not value: self._pan_key = None else: value = validators.string(value) value = value.lower() if value not in ['alt', 'ctrl', 'meta', 'shift']: raise errors.HighchartsValueError(f'pan_key expects a value of "alt", ' f'"ctrl", "meta", or "shift". Was: ' f'{value}') self._pan_key = value @property def panning(self) -> Optional[PanningOptions]: """Configures panning behavior in a chart. .. hint:: Best used with :meth:`Chart.pan_key` to combine zooming and panning. .. note:: On touch devices, when the :meth:`Tooltip.follow_touch_move` property is ``True`` (default), panning requires two fingers. To allow panning with one finger, set ``follow_touch_move`` to ``False``. :returns: Configuration settings for panning behavior. :rtype: :class:`PanningOptions` or :obj:`None <python:None>` """ return self._panning @panning.setter def panning(self, value): if value is None: self._panning = None else: if isinstance(value, bool): value = { 'enabled': value } value = validate_types(value, types = PanningOptions) self._panning = value @property def parallel_axes(self) -> Optional[ParallelAxesOptions]: """Common options for all Y-Axes rendered in a parallel coordinates plot. .. note:: This feature requires in JavaScript ``modules/parallel-coordinates.js``. :rtype: :class:`ParallelAxesOptions` or :obj:`None <python:None>` """ return self._parallel_axes @parallel_axes.setter @class_sensitive(ParallelAxesOptions) def parallel_axes(self, value): self._parallel_axes = value @property def parallel_coordinates(self) -> Optional[bool]: """If ``True``, renders charts as a parallel coordinates plot. Defaults to ``False``. In a parallel coordinates plot (||-coords) by default all required Y-axes are generated and the legend is disabled. .. note:: This feature requires the JavaScript module ``modules/parallel-coordinates.js``. .. seealso:: * `Parallel Coordinates Demo <https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples//highcharts/demo/parallel-coordinates/>`_ :returns: Flag indicating whether the chart is a parallel coordinates plot. :rtype: :class:`bool <python:bool>` or :obj:`None <python:None>` """ return self._parallel_coordinates @parallel_coordinates.setter def parallel_coordinates(self, value): if value is None: self._parallel_coordinates = None else: self._parallel_coordinates = bool(value) @property def plot_background_color(self) -> Optional[str | Gradient | Pattern]: """The background color or gradient for the plot area. Defaults to ``None``. :returns: The background color for the plot area. :rtype: :class:`str <python:str>`, :class:`Gradient`, :class:`Pattern``, or :obj:`None <python:None>` """ return self._plot_background_color @plot_background_color.setter def plot_background_color(self, value): from highcharts_core import utility_functions self._plot_background_color = utility_functions.validate_color(value) @property def plot_background_image(self) -> Optional[str]: """The URL for an image to use as the background of the plot area. .. hint:: To set an image as the background for the entire chart, set a CSS background image to the container element. .. note:: Note that for the image to be applied to exported charts, its URL needs to be accessible by the export server. :rtype: :class:`str <python:str>` or :obj:`None <python:None>` :raises HighchartsValueError: if a value is supplied that is not a URL or not path-like """ return self._plot_background_image @plot_background_image.setter def plot_background_image(self, value): if not value: self._plot_background_image = None else: try: self._plot_background_image = validators.url( value, allow_special_ips=os.getenv("HCP_ALLOW_SPECIAL_IPS", False) ) except ValueError: try: self._plot_background_image = validators.path(value) except ValueError: raise errors.HighchartsValueError(f'value provided ({value}) not a ' f'valid URL or path') @property def plot_border_color(self) -> Optional[str | Gradient | Pattern]: """The color of the outer chart border. Defaults to ``'#cccccc'``. :returns: The color of the outer chart border. :rtype: :class:`str <python:str>`, :class:`Gradient`, :class:`Pattern``, or :obj:`None <python:None>` """ return self._plot_border_color @plot_border_color.setter def plot_border_color(self, value): from highcharts_core import utility_functions self._plot_border_color = utility_functions.validate_color(value) @property def plot_border_width(self) -> Optional[int | float | Decimal]: """The border width (in pixels) applied to the outer chart border. Defaults to ``0``. :returns: The border width to apply to the outer chart border. :rtype: numeric or :obj:`None <python:None>` """ return self._plot_border_width @plot_border_width.setter def plot_border_width(self, value): self._plot_border_width = validators.numeric(value, allow_empty = True) @property def plot_shadow(self) -> Optional[bool | ShadowOptions]: """Configuration of a drop shadow applied to the plot area. Accepts either a boolean value of ``False`` which disables any shadow, or a :class:`ShadowOptions` instance with the applicable configuration. Defaults to ``False``. .. warning:: Requires that :meth:`Chart.plot_background_color` be set. :rtype: :class:`bool <python:bool>` or :obj:`None <python:None>` """ return self._plot_shadow @plot_shadow.setter def plot_shadow(self, value): if value is None: self._plot_shadow = None elif value is False: self._plot_shadow = False else: value = validate_types(value, types = ShadowOptions, allow_none = False) self._plot_shadow = value @property def polar(self) -> Optional[bool]: """If ``True``, cartesian charts like line, spline, area, and column are transformed into the polar coordinate system. This produces polar charts (also known as radar charts). Defaults to ``False``. :returns: Flag indicating whether to render the chart as a polar chart. :rtype: :class:`bool <python:bool>` or :obj:`None <python:None>` """ return self._polar @polar.setter def polar(self, value): if value is None: self._polar = None else: self._polar = bool(value) @property def reflow(self) -> Optional[bool]: """If ``True``, reflows the chart to fit the width of the container ``div`` when the window is resized. Defaults to ``True``. :returns: Flag indicating whether to reflow the chart in response to window resizing. :rtype: :class:`bool <python:bool>` or :obj:`None <python:None>` """ return self._reflow @reflow.setter def reflow(self, value): if value is None: self._reflow = None else: self._reflow = bool(value) @property def render_to(self) -> Optional[str]: """The ID of the HTML element where the chart will be rendered. .. note:: In JavaScript, the HTML element can also be passed by direct reference, or as the first argument of the chart constructor, in which case the option is not needed. :rtype: :class:`str <python:str>` or :obj:`None <python:None>` """ return self._render_to @render_to.setter def render_to(self, value): self._render_to = validators.string(value, allow_empty = True) @property def scrollable_plot_area(self) -> Optional[ScrollablePlotArea]: """Configuration settings to make the plot area scrollable. This feature provides a minimum size for the plot area of the chart. If the size gets smaller than this, typically on mobile devices, a native browser scrollbar is presented. This scrollbar provides smooth scrolling for the contents of the plot area, whereas the title, legend and unaffected axes are fixed. .. hint:: Since v7.1.2, a scrollable plot area can be defined for either horizontal or vertical scrolling, depending on whether the `minimum_width` or `minimum_height` options are set. :rtype: :class:`ScrollablePlotArea` or :obj:`None <python:None>` """ return self._scrollable_plot_area @scrollable_plot_area.setter @class_sensitive(ScrollablePlotArea) def scrollable_plot_area(self, value): self._scrollable_plot_area = value @property def selection_marker_fill(self) -> Optional[str | Gradient | Pattern]: """The background color or the marker square when selecting (zooming in on) an area of the chart. Defaults to ``'rgba(51,92,173,0.25)'``. :returns: The backgorund color of the marker square when selecting an area of the chart. :rtype: :class:`str <python:str>`, :class:`Gradient`, :class:`Pattern``, or :obj:`None <python:None>` """ return self._selection_marker_fill @selection_marker_fill.setter def selection_marker_fill(self, value): self._selection_marker_fill = utility_functions.validate_color(value) @property def shadow(self) -> Optional[bool | ShadowOptions]: """Configuration of a drop shadow applied to the outer chart area. Accepts either a boolean value of ``False`` which disables any shadow, or a :class:`ShadowOptions` instance with the applicable configuration. Defaults to ``False``. .. warning:: Requires that :meth:`Chart.background_color` be set. :rtype: :class:`bool <python:bool>` or :obj:`None <python:None>` """ return self._shadow @shadow.setter def shadow(self, value): if value is None: self._shadow = None elif value is False: self._shadow = False else: value = validate_types(value, types = ShadowOptions, allow_none = False) self._shadow = value @property def show_axes(self) -> Optional[bool]: """If ``True``, shows axes initially (before series have been added to the chart). .. warning:: This property only applies to empty charts where series are added dynamically. :returns: Flag indicating whether to show axes on empty dynamic charts before series have been added. :rtype: :class:`bool <python:bool>` or :obj:`None <python:None>` """ return self._show_axes @show_axes.setter def show_axes(self, value): if value is None: self._show_axes = None else: self._show_axes = bool(value) @property def spacing(self) -> Optional[List[int | float | Decimal]]: """The distance between the outer edge of the chart and the content, like title or legend, or axis title and labels if present. The numbers in the array designate top, right, bottom and left respectively. By default, ``[10,10,15,10]``. .. note:: This property is a convenience property to consolidate simple spacing configuration across the ``spacing_top``, ``spacing_right``, ``spacing_bottom``, and ``spacing_left`` options. Values will be propagated between all options. :rtype: :class:`list <python:list>` of four numeric values or :obj:`None <python:None>` """ result = [self.spacing_top, self.spacing_right, self.spacing_bottom, self.spacing_left] if not any(result): return None return result @spacing.setter def spacing(self, value): if value is None: self.spacing_top = None self.spacing_right = None self.spacing_bottom = None self.spacing_left = None elif checkers.is_iterable(value): if len(value) != 4: raise errors.HighchartsValueError(f'spacing expects either a single value' f' or an iterable of four values. ' f'Received an iterable of {len(value)} ' f'values ({value})') if value[0] == 'null': self.spacing_top = None else: self.spacing_top = value[0] if value[1] == 'null': self.spacing_right = None else: self.spacing_right = value[1] if value[2] == 'null': self.spacing_bottom = None else: self.spacing_bottom = value[2] if value[3] == 'null': self.spacing_left = None else: self.spacing_left = value[3] else: self.spacing_top = value self.spacing_right = value self.spacing_bottom = value self.spacing_left = value @property def spacing_bottom(self) -> Optional[int | float | Decimal]: """The spacing between the bottom edge of the chart and the content (plot area, axis title and labels, title, subtitle or legend in top position). By default, ``15``. :rtype: numeric or :obj:`None <python:None>` """ return self._spacing_bottom @spacing_bottom.setter def spacing_bottom(self, value): self._spacing_bottom = validators.numeric(value, allow_empty = True) @property def spacing_left(self) -> Optional[int | float | Decimal]: """The spacing between the left edge of the chart and the content (plot area, axis title and labels, title, subtitle or legend in top position). Defaults to ``10``. :rtype: numeric or :obj:`None <python:None>` """ return self._spacing_left @spacing_left.setter def spacing_left(self, value): self._spacing_left = validators.numeric(value, allow_empty = True) @property def spacing_right(self) -> Optional[int | float | Decimal]: """The spacing between the right edge of the chart and the content (plot area, axis title and labels, title, subtitle or legend in top position). Defaults to ``10``. :rtype: numeric or :obj:`None <python:None>` """ return self._spacing_right @spacing_right.setter def spacing_right(self, value): self._spacing_right = validators.numeric(value, allow_empty = True) @property def spacing_top(self) -> Optional[int | float | Decimal]: """The spacing between the top edge of the chart and the content (plot area, axis title and labels, title, subtitle or legend in top position). Defaults to ``10``. :rtype: numeric or :obj:`None <python:None>` """ return self._spacing_top @spacing_top.setter def spacing_top(self, value): self._spacing_top = validators.numeric(value, allow_empty = True) @property def style(self) -> Optional[str | dict]: """Additional CSS styles to apply inline to the container div. Defaults to ``'{"fontFamily": "\"Lucida Grande\", \"Lucida Sans Unicode\", Verdana, Arial, Helvetica, sans-serif","fontSize":"12px"}'``. .. note:: Since the default font styles are applied in the renderer, it is ignorant of the individual chart options and must be set globally. :rtype: :class:`str <python:str>` or :class:`dict <python:dict>` or :obj:`None <python:None>` """ return self._style @style.setter def style(self, value): try: self._style = validators.dict(value, allow_empty = True) except (ValueError, TypeError): self._style = validators.string(value, allow_empty = True, coerce_value = True) @property def styled_mode(self) -> Optional[bool]: """If ``True``, sets the chart to operate in **styled mode**, where no presentational attributes or CSS are applied to the chart SVG. Instead, CSS rules are required to style the chart. Defaults to ``False``. .. seealso:: * `Available CSS Styles and Variables <https://www.highcharts.com/docs/chart-design-and-style/style-by-css>`__. * The Default Style Sheet: `https://code.highcharts.com/css/highcharts.css <https://code.highcharts.com/css/highcharts.css>`_. :rtype: :class:`bool <python:bool>` or :obj:`None <python:None>` """ return self._styled_mode @styled_mode.setter def styled_mode(self, value): if value is None: self._styled_mode = None else: self._styled_mode = bool(value) @property def type(self) -> Optional[str]: """The default series type for the chart. Defaults to ``'line'``. Can be any of the chart types listed under :class:`PlotOptions` and :class:`Series`, or can be a series provided by an additional module. :rtype: :class:`str <python:str>` or :obj:`None <python:None>` """ return self._type @type.setter def type(self, value): self._type = validators.string(value, allow_empty = True) @property def width(self) -> Optional[constants.EnforcedNullType | int | float | Decimal | str]: """An explicit width for the chart. Defaults to :class:`EnforcedNull <EnforcedNullType>`` which indicates a JavaScript value of ``null`` (as opposed to :obj:`None <python:None>` which results in ``undefined`` when converted JavaScript.) If a number, the width is given in pixels. If given a percentage string (for example ``'56%'``), the width is given as the percentage of the actual chart width. This allows for preserving the aspect ratio across responsive sizes. By default (when null) the width is calculated from the offset width of the containing element. :rtype: :class:`EnforcedNullType` or numeric or :class:`str <python:str>` or :obj:`None <python:None>` """ return self._width @width.setter def width(self, value): if value is None: self._width = None else: try: try: self._width = validators.numeric(value, allow_empty = False, minimum = 0) except ValueError: self._width = validators.string(value, allow_empty = False) except ValueError: raise errors.HighchartsValueError('Unable to resolve value to a ' 'supported data type.') @property def zooming(self) -> Optional[ZoomingOptions]: """Chart zooming configuration. :rtype: :class:`ZoomingOptions <highcharts_maps.options.chart.zooming.ZoomingOptions>` or :obj:`None <python:None>` """ return self._zooming @zooming.setter @class_sensitive(ZoomingOptions) def zooming(self, value): self._zooming = value @classmethod def _get_kwargs_from_dict(cls, as_dict): kwargs = { 'align_thresholds': as_dict.get('alignThresholds', None), 'align_ticks': as_dict.get('alignTicks', None), 'allow_mutating_data': as_dict.get('allowMutatingData', None), 'animation': as_dict.get('animation', None), 'axis_layout_runs': as_dict.get('axisLayoutRuns', None), 'background_color': as_dict.get('backgroundColor', None), 'border_color': as_dict.get('borderColor', None), 'border_radius': as_dict.get('borderRadius', None), 'border_width': as_dict.get('borderWidth', None), 'class_name': as_dict.get('className', None), 'color_count': as_dict.get('colorCount', None), 'display_errors': as_dict.get('displayErrors', None), 'events': as_dict.get('events', None), 'height': as_dict.get('height', None), 'ignore_hidden_series': as_dict.get('ignoreHiddenSeries', None), 'inverted': as_dict.get('inverted', None), 'margin': as_dict.get('margin', None), 'margin_bottom': as_dict.get('marginBottom', None), 'margin_left': as_dict.get('marginLeft', None), 'margin_right': as_dict.get('marginRight', None), 'margin_top': as_dict.get('marginTop', None), 'number_formatter': as_dict.get('numberFormatter', None), 'options_3d': as_dict.get('options3d', None), 'pan_key': as_dict.get('panKey', None), 'panning': as_dict.get('panning', None), 'parallel_axes': as_dict.get('parallelAxes', None), 'parallel_coordinates': as_dict.get('parallelCoordinates', None), 'plot_background_color': as_dict.get('plotBackgroundColor', None), 'plot_background_image': as_dict.get('plotBackgroundImage', None), 'plot_border_color': as_dict.get('plotBorderColor', None), 'plot_border_width': as_dict.get('plotBorderWidth', None), 'plot_shadow': as_dict.get('plotShadow', None), 'polar': as_dict.get('polar', None), 'reflow': as_dict.get('reflow', None), 'render_to': as_dict.get('renderTo', None), 'scrollable_plot_area': as_dict.get('scrollablePlotArea', None), 'selection_marker_fill': as_dict.get('selectionMarkerFill', None), 'shadow': as_dict.get('shadow', None), 'show_axes': as_dict.get('showAxes', None), 'spacing': as_dict.get('spacing', None), 'spacing_bottom': as_dict.get('spacingBottom', None), 'spacing_left': as_dict.get('spacingLeft', None), 'spacing_top': as_dict.get('spacingTop', None), 'spacing_right': as_dict.get('spacingRight', None), 'style': as_dict.get('style', None), 'styled_mode': as_dict.get('styledMode', None), 'type': as_dict.get('type', None), 'width': as_dict.get('width', None), 'zooming': as_dict.get('zooming', None), } return kwargs def _to_untrimmed_dict(self, in_cls = None) -> dict: untrimmed = { 'alignThresholds': self.align_thresholds, 'alignTicks': self.align_ticks, 'allowMutatingData': self.allow_mutating_data, 'animation': self.animation, 'axisLayoutRuns': self.axis_layout_runs, 'backgroundColor': self.background_color, 'borderColor': self.border_color, 'borderRadius': self.border_radius, 'borderWidth': self.border_width, 'className': self.class_name, 'colorCount': self.color_count, 'displayErrors': self.display_errors, 'events': self.events, 'height': self.height, 'ignoreHiddenSeries': self.ignore_hidden_series, 'inverted': self.inverted, 'margin': self.margin, 'marginBottom': self.margin_bottom, 'marginLeft': self.margin_left, 'marginRight': self.margin_right, 'marginTop': self.margin_top, 'numberFormatter': self.number_formatter, 'options3d': self.options_3d, 'panKey': self.pan_key, 'panning': self.panning, 'parallelAxes': self.parallel_axes, 'parallelCoordinates': self.parallel_coordinates, 'plotBackgroundColor': self.plot_background_color, 'plotBackgroundImage': self.plot_background_image, 'plotBorderColor': self.plot_border_color, 'plotBorderWidth': self.plot_border_width, 'plotShadow': self.plot_shadow, 'polar': self.polar, 'reflow': self.reflow, 'renderTo': self.render_to, 'scrollablePlotArea': self.scrollable_plot_area, 'selectionMarkerFill': self.selection_marker_fill, 'shadow': self.shadow, 'showAxes': self.show_axes, 'spacing': self.spacing, 'spacingBottom': self.spacing_bottom, 'spacingLeft': self.spacing_left, 'spacingRight': self.spacing_right, 'spacingTop': self.spacing_top, 'style': self.style, 'styledMode': self.styled_mode, 'type': self.type, 'width': self.width, 'zooming': self.zooming, } return untrimmed