colorlab
clone your own copy | download snapshot

Snapshots | iceberg

Inside this repository

textbox.py
text/x-python

Download raw (4.5 KB)

#!/usr/bin/env python
#! -*- coding: utf-8 -*-

from chiplotle.geometry.core.coordinate import Coordinate

from font import Font
from textline import Textline
from copy import deepcopy

class Charbuff (object):
    def __init__ (self, chars=[], offset=0, letterSpacing=0):
        self.offset = offset
        self.chars = chars
        self.letterSpacing = letterSpacing

    def add(self, char):
        self.chars.append(char)

    @property
    def width(self):
        return reduce(lambda x, char: x + char.width + char.margins[1] + self.letterSpacing, self.chars, self.offset)

# Textbox. Wrapper for lines.
class Textbox (object):
    alignLeft = 'left'
    alignCenter = 'center'
    alignRight = 'right'
    
    def __init__ (self, font = False, width = False, position = False, align = False, height = False, lineHeight = 1, letterSpacing = 0):
        if isinstance(position, Coordinate):
            self.position = position
        else:
            self.position = Coordinate(0, 0)
        
        self.width = width if width <> False else 0
        self.maxHeight = height if height <> False else False
        self.height = 0
        self.int_y = 0
        self.lineHeight = lineHeight
        self.letterSpacing =letterSpacing
        
        self._lines = []
        
        if isinstance (font, Font):
            self.font = font
        else:
            self.font = None
        
        if align <> False:
            self.align = align
        else:
            self.align = self.alignLeft
        
        self.newLine()
    
    @property
    def lines (self):
        buff = []
        for line in self._lines:
            if self.align == self.alignCenter or self.align == self.alignRight:
                line = deepcopy(line)
                delta_x = (self.width - line.int_x) * .5 if self.align == self.alignCenter else (self.width - line.int_x)
                line.offset((delta_x, 0))
            buff.append(line)
        return buff

    def clear (self):
        self._lines = []
        self.newLine()
    
    def newLine (self):
        for line in self._lines:
            line.offset((0, self.font.height * self.lineHeight))
        
        self._lines.append(Textline(width = self.width, position = Coordinate(self.position[0], self.position[1]), letterSpacing = self.letterSpacing))
        #self.int_y += self.font.height * self.lineHeight
        self.height += self.font.height * self.lineHeight
            
        return True
            
    def newCharBuff (self, appendix=[]):
        buff = Charbuff(chars=[], letterSpacing = self.letterSpacing)
        return buff

    def setFont (self, font):
        if isinstance (font, Font):
            self.font = font
    
    def setSize (self, size):
        if type (size) == int:
            self.size = size
    
    def insertText (self, text):
        # Charbuff collects texts in words and then tries to write it
        buff = self.newCharBuff()
        
        for char in text:
            if char  == '\n':
                if self.newLine() == False:
                    # Could not add the new line. Return False
                    return False
                else:
                    self.writeBuff(buff)
                    buff = self.newCharBuff()
            else:
                charObj = self.font.getChar(char)
                
                if charObj <> False:
                    if char == ' ':
                        self.writeBuff(buff, charObj)
                        buff = self.newCharBuff()
                    else:
                        buff.add(charObj)
        self.writeBuff(buff)
        
        return True

    def writeBuff(self, buff, appendix=None):
        appendixBuff = None
        
        if len(self._lines) == 0:
            self.newLine()
            
        if self._lines[-1].room_for(buff.width):
            if appendix is not None:
                appendixBuff = self.newCharBuff()
        else:
            self.newLine()
            
        self.addBuffToLine(buff, self._lines[-1])
        
        # if appendixBuff is not None and self._lines[-1].room_for(appendixBuff.width):
        #     self.addBuffToLine(appendixBuff, self.lines[-1])

    def addBuffToLine(self, buff, line):
        for char in buff.chars:
            line.add(char)

    def write (self, plotter):
        for line in self.lines:
            plotter.write(line.characters)
                                            
    def hpgl (self, offset = (0,0)):
        hpgl = [line.hpgl(offset) for line in self.lines]
        
        return ';'.join (hpgl)