Source code for plie.text

from collections import namedtuple
from functools import partial
from textwrap import wrap


[docs]class Text: """ Text is the universal class for dealing with all single text snippets. Text helps with basic formatting, justification, word wrapping to the appropriate width and acts as a way to contain a block of text for applying styles to it or developing a layout. Args: text: the text to display (can be changed later callout: an attribute made available for storing a function, it is used if this Text object gets selected by some event. justify: specifies which justification the text should have, options are: 'left' where all the text aligns with the left edge, 'center' where all the text is centered in the middle of the, available space 'right' where all the text aligns with the right edge bounds: the bounding box for the Text object in screen space cells, will be set automatically by Renderer usually Returns: an initialized Text object """ def __init__(self, text='', callout=None, justify='left', bounds=None, replace_whitespace=True): self.callout = callout self.justify = justify self.cells = {} self._replace_whitespace = replace_whitespace 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 if self.width: self.text = '\n'.join(wrap(text, self.width, replace_whitespace=self._replace_whitespace)) else: self.text = text def __repr__(self): return 'Text(text=%r, callout=%r, justify=%r, bounds=%r)' % (self.text, self.callout, self.justify, (self.width, self.height)) def __str__(self): # TODO decide if this should have styling and formatting applied to it return self.text
[docs] def update(self, bounds=None, text=None, **kwargs): """For changing internal state, including updating the text to display. update() accepts ``**kwargs``, so any keyword argument passed during initialization can be passed again, to change the stored value. Returns: True if updating went well """ if bounds: self._update_bounds(bounds) if text: if self.width: self.text = '\n'.join(wrap(text, self.width, replace_whitespace=self._replace_whitespace)) else: self.text = text if kwargs.get('callout', False): self.callout = kwargs['callout'] if kwargs.get('justify', False): self.justify = kwargs['justify'] if kwargs.get('replace_whitespace', False): self._replace_whitespace = kwargs['replace_whitespace']
@property def lines(self): """ Returns: the number of lines that the Text instance uses """ return len(self.text.split('\n'))
[docs] def as_cells(self): """ Translates the internal state and translates it into a screen-space cell dict of size bounds Returns: Dictionary with keys of format (x,y), of size bounds and single character strings as the values. """ operation = {'left': partial(str.ljust), 'center': partial(str.center), 'right': partial(str.rjust)} lines = self.text.split('\n') formatted = [] for line in lines: # apply the appropriate string method to each line formatted.append(operation[self.justify](line, self.width)) # Add each cell to the dictionary for x, y in [(x, y) for y in range(self.height) for x in range(self.width)]: try: self.cells[(x,y)] = formatted[y][x] except IndexError: self.cells[(x,y)] = ' ' return self.cells
def _update_by_cell(self, cell, char): """ Update a particular cell in the internal dictionary Args: cell: A tuple specifying which cell to modify char: A single character string to change the cell too. """ pass def _update_bounds(self, bounds): 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: pass