"""document layout engine.""" class Layout: """the document layout engine .widgets -- elements are kept in this list. read-only, use add to add items to it. """ def __init__(self,rect=None): """initialize the object with the size of the box.""" self._widgets = [] self.rect = rect def add(self,e): """add a document element to the layout. a document element may be - a tuple (w,h) if it is a whitespace element - a tuple (0,h) if it is a linebreak element - an integer -1,0,1 if it is a command to start a new block of elements that are aligned either left,center, or right. - an object with a .rect (for size) -- such as a word element - an object with a .rect (for size) and .align -- such as an image element """ self._widgets.append(e) def resize(self): """resize the layout this method recalculates the position of all document elements after they have been added to the document. .rect.x,y will be updated for all objects. """ self.init() self.widgets = [] for e in self._widgets: if type(e) is tuple and e[0] != 0: self.do_space(e) elif type(e) is tuple and e[0] == 0: self.do_br(e[1]) elif type(e) is int: self.do_block(align=e) elif hasattr(e,'align'): self.do_align(e) else: self.do_item(e) self.line() self.rect.h = max(self.y,self.left_bottom,self.right_bottom) def init(self): self.x,self.y = self.rect.x,self.rect.y self.left = self.rect.left self.right = self.rect.right self.left_bottom = 0 self.right_bottom = 0 self.y = self.rect.y self.x = self.rect.x self.h = 0 self.items = [] self.align = -1 def getleft(self): if self.y > self.left_bottom: self.left = self.rect.left return self.left def getright(self): if self.y > self.right_bottom: self.right = self.rect.right return self.right def do_br(self,h): self.line() self.h = h def do_block(self,align=-1): self.line() self.align = align def do_align(self,e): align = e.align ox,oy,oh = self.x,self.y,self.h w,h = e.rect.w,e.rect.h if align == 0: self.line() self.x = self.rect.left + (self.rect.width-w)/2 self.fit = 0 elif align == -1: self.line() self.y = max(self.left_bottom,self.y + self.h) self.h = 0 self.x = self.rect.left elif align == 1: self.line() self.y = max(self.right_bottom,self.y + self.h) self.h = 0 self.x = self.rect.left + (self.rect.width-w) e.rect.x,e.rect.y = self.x,self.y self.x = self.x + w self.y = self.y if align == 0: self.h = max(self.h,h) self.y = self.y + self.h self.x = self.getleft() self.h = 0 elif align == -1: self.left = self.x self.left_bottom = self.y + h self.x,self.y,self.h = ox + w,oy,oh elif align == 1: self.right = self.x - w self.right_bottom = self.y + h self.x,self.y,self.h = ox,oy,oh self.widgets.append(e) def do_space(self,e): w,h = e if self.x+w >= self.getright(): self.line() else: self.items.append(e) self.h = max(self.h,h) self.x += w def do_item(self,e): w,h = e.rect.w,e.rect.h if self.x+w >= self.getright(): self.line() self.items.append(e) self.h = max(self.h,h) self.x += w def line(self): x1 = self.getleft() x2 = self.getright() align = self.align y = self.y if len(self.items) != 0 and type(self.items[-1]) == tuple: del self.items[-1] w = 0 for e in self.items: if type(e) == tuple: w += e[0] else: w += e.rect.w if align == -1: x = x1 elif align == 0: x = x1 + ((x2-x1)-w)/2 self.fit = 0 elif align == 1: x = x2 - w for e in self.items: if type(e) == tuple: x += e[0] else: e.rect.x,e.rect.y = x,y self.widgets.append(e) x += e.rect.w self.items = [] self.y = self.y + self.h self.x = self.getleft() self.h = 0 # vim: set filetype=python sts=4 sw=4 noet si :