Source code for plie.mutlitext

from textwrap import wrap
from plie.text import Text
from plie.view import Bounds


[docs]class MultiText(Text): """ MultiText displays sequences of text, including bulleted lists. MultiText can be used for lists of text, menus, and other things that involve multiple distinct elements of vertically arranged text. Args: texts: sequence of text strings to display (preferably immutable) bullet_choice: a string that will be used as the bullet for each list item justify: which justification to use for the list items bounds: bounding box specifying size in cells (x,y), usually set by Renderer """ def __init__(self, texts=(), bullet_choice='', justify='left', bounds=None): self.bullet_choice = bullet_choice self.justify = justify self.cells = {} try: # preferred method for handling bounds (as a namedtuple) self.width = bounds.width self.height = bounds.height except AttributeError: if isinstance(bounds, (list, tuple)): # fall back if it's not a namedtuple, uses format (width, height) self.width = bounds[0] self.height = bounds[1] else: self.width = 0 self.height = 0 self.texts = [] if texts: self._update_texts(texts) def __repr__(self): return 'MultiText(texts=%r, bullet_choice=%r, justify=%r, bounds=%r)' % \ (self.texts, self.bullet_choice, self.justify, (self.width, self.height))
[docs] def __str__(self): """ creates a printable string of this instance Individual texts in in the MultiText instance are prefixed with self.bullet_choice, multiline texts have subsequent lines indented to where they start at an equal indent to the first line Returns: a printable string of the contents of this instance """ lines = [] for text_elem in self.texts: for i, line in enumerate(str(text_elem).split('\n')): if i == 0: lines.append(self.bullet_choice + line) else: blank_space = ' ' * len(self.bullet_choice) lines.append(blank_space + line) return '\n'.join(lines)
def __len__(self): return len(self.texts) def __getitem__(self, index): return self.texts[index]
[docs] def update(self, bounds=None, texts=None, specific_text=(), bullet_choice=None): """For changing internal state Args: bounds: update the bounds, either a tuple or a Bounds object texts: update the entire list of texts specific_text: a tuple of format (new_text_string, index) bullet_choice: update the bullet_choice Returns: nothing, but updates the internal state """ if bounds: # TODO verify that this works super()._update_bounds(bounds) for text_elem in self.texts: text_elem._update_bounds(bounds) if texts: self._update_texts(texts) if specific_text: try: self.texts[specific_text[1]].update(text=specific_text[0]) except IndexError: raise IndexError("Index given ({}) for which text to update wasn't found".format( specific_text[1])) if bullet_choice: self.bullet_choice = bullet_choice
[docs] def as_cells(self): """ Translates the internal state into a cell space based format for transferring Returns: a dictionary cell space representation of all the contained text objects """ output_lines = str(self).split('\n') cells_to_output = {} for x, y in [(x, y) for y in range(self.height) for x in range(self.width)]: try: cells_to_output[(x, y)] = output_lines[y][x] except IndexError: cells_to_output[(x, y)] = '' return cells_to_output
def _update_texts(self, texts): for text_elem in texts: if self.width: num_lines = len(wrap(text_elem, self.width, replace_whitespace=False)) space_remaining_after_bullet = self.width - len(self.bullet_choice) elem_bounds = Bounds(space_remaining_after_bullet, num_lines) self.texts.append(Text(text=text_elem, justify=self.justify, bounds=elem_bounds)) else: self.texts.append(Text(text=text_elem, justify=self.justify))