"""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
		
	def getwidths(self):
		self._line = 0
		self._min = 0
		self._max = 0
			
		for e in self._widgets:
			if type(e) is tuple and e[0] != 0:
				self._min = max(self._min,e[0])
				self._line += e[0]
				self._max = max(self._max,self._line)
			elif type(e) is tuple and e[0] == 0:
				self._line = 0
			elif type(e) is int:
				self._line = 0
			elif hasattr(e,'align'):
				self._line = 0
				self._min = max(self._min,e.rect.w)
				self._line += e.rect.w
				self._max = max(self._max,self._line)
			else:
				self._min = max(self._min,e.rect.w)
				self._line += e.rect.w
				self._max = max(self._max,self._line)

		return self._min,self._max


# vim: set filetype=python sts=4 sw=4 noet si :
