# encoding: utf-8 """ Styles object, container for all objects in the styles part. """ from __future__ import ( absolute_import, division, print_function, unicode_literals ) from warnings import warn from . import BabelFish from .latent import LatentStyles from ..shared import ElementProxy from .style import BaseStyle, StyleFactory class Styles(ElementProxy): """ A collection providing access to the styles defined in a document. Accessed using the :attr:`.Document.styles` property. Supports ``len()``, iteration, and dictionary-style access by style name. """ __slots__ = () def __contains__(self, name): """ Enables `in` operator on style name. """ internal_name = BabelFish.ui2internal(name) for style in self._element.style_lst: if style.name_val == internal_name: return True return False def __getitem__(self, key): """ Enables dictionary-style access by UI name. Lookup by style id is deprecated, triggers a warning, and will be removed in a near-future release. """ style_elm = self._element.get_by_name(BabelFish.ui2internal(key)) if style_elm is not None: return StyleFactory(style_elm) style_elm = self._element.get_by_id(key) if style_elm is not None: msg = ( 'style lookup by style_id is deprecated. Use style name as ' 'key instead.' ) warn(msg, UserWarning) return StyleFactory(style_elm) raise KeyError("no style with name '%s'" % key) def __iter__(self): return (StyleFactory(style) for style in self._element.style_lst) def __len__(self): return len(self._element.style_lst) def add_style(self, name, style_type, builtin=False): """ Return a newly added style object of *style_type* and identified by *name*. A builtin style can be defined by passing True for the optional *builtin* argument. """ style_name = BabelFish.ui2internal(name) if style_name in self: raise ValueError("document already contains style '%s'" % name) style = self._element.add_style_of_type( style_name, style_type, builtin ) return StyleFactory(style) def default(self, style_type): """ Return the default style for *style_type* or |None| if no default is defined for that type (not common). """ style = self._element.default_for(style_type) if style is None: return None return StyleFactory(style) def get_by_id(self, style_id, style_type): """ Return the style of *style_type* matching *style_id*. Returns the default for *style_type* if *style_id* is not found or is |None|, or if the style having *style_id* is not of *style_type*. """ if style_id is None: return self.default(style_type) return self._get_by_id(style_id, style_type) def get_style_id(self, style_or_name, style_type): """ Return the id of the style corresponding to *style_or_name*, or |None| if *style_or_name* is |None|. If *style_or_name* is not a style object, the style is looked up using *style_or_name* as a style name, raising |ValueError| if no style with that name is defined. Raises |ValueError| if the target style is not of *style_type*. """ if style_or_name is None: return None elif isinstance(style_or_name, BaseStyle): return self._get_style_id_from_style(style_or_name, style_type) else: return self._get_style_id_from_name(style_or_name, style_type) @property def latent_styles(self): """ A |LatentStyles| object providing access to the default behaviors for latent styles and the collection of |_LatentStyle| objects that define overrides of those defaults for a particular named latent style. """ return LatentStyles(self._element.get_or_add_latentStyles()) def _get_by_id(self, style_id, style_type): """ Return the style of *style_type* matching *style_id*. Returns the default for *style_type* if *style_id* is not found or if the style having *style_id* is not of *style_type*. """ style = self._element.get_by_id(style_id) if style is None or style.type != style_type: return self.default(style_type) return StyleFactory(style) def _get_style_id_from_name(self, style_name, style_type): """ Return the id of the style of *style_type* corresponding to *style_name*. Returns |None| if that style is the default style for *style_type*. Raises |ValueError| if the named style is not found in the document or does not match *style_type*. """ return self._get_style_id_from_style(self[style_name], style_type) def _get_style_id_from_style(self, style, style_type): """ Return the id of *style*, or |None| if it is the default style of *style_type*. Raises |ValueError| if style is not of *style_type*. """ if style.type != style_type: raise ValueError( "assigned style is type %s, need type %s" % (style.type, style_type) ) if style == self.default(style_type): return None return style.style_id