import os
import re

from PresentationObject import PresentationObject

from qt import *
from qtcanvas import *

true = success = 1
false = failure = 0

class td( PresentationObject ):
	"""
	&lt;td&gt; is used to display content in a table. It can only be used
	in &lt;tr&gt; since &lt;tr&gt; is used to group adjacent table cells.
	If an object is too large to fit within the cell, such as an
	&lt;img&gt;, it will be scaled down.<br>
	<br>
	An example:
	<pre>
	&lt;table width="75%"&gt;
	  &lt;tr&gt;
	    &lt;td width="50%"&gt;
	      Left cell on the top row.
	    &lt;/td&gt;
	    &lt;td width="50%"&gt;
	      Right cell on the top row.
	    &lt;/td&gt;
	  &lt;/tr&gt;
	  &lt;tr&gt;
	    &lt;td width="100%"&gt;
	      Cell which acts as colspan="2" in HTML.
	    &lt;/td&gt;
	  &lt;/tr&gt;
	&lt;/table&gt;
	</pre>

	<b>Properties:</b>
	<ul>
	  <li>
	    <i>bgcolor</i>: background colour for this cell. By default, no
	    background colour is drawn.
	  </li>
	  <li>
	    <i>bgpattern</i>: used in conjunction with <i>bgcolor</i>.
	    Possible values are:
	    <ul>
	      <li>
	        <b>SolidPattern</b>, solid (100%) fill pattern.
	      </li>
	      <li>
	        <b>Dense1Pattern</b>, 94% fill pattern.
	      </li>
	      <li>
	        <b>Dense2Pattern</b>, 88% fill pattern.
	      </li>
	      <li>
	        <b>Dense3Pattern</b>, 63% fill pattern.
	      </li>
	      <li>
	        <b>Dense4Pattern</b>, 50% fill pattern.
	      </li>
	      <li>
	        <b>Dense5Pattern</b>, 37% fill pattern.
	      </li>
	      <li>
	        <b>Dense6Pattern</b>, 12% fill pattern.
	      </li>
	      <li>
	        <b>Dense7Pattern</b>, 6% fill pattern.
	      </li>
	      <li>
	        <b>HorPattern</b>, horizontal lines pattern.
	      </li>
	      <li>
	        <b>VerPattern</b>, vertical lines pattern.
	      </li>
	      <li>
	        <b>CrossPattern</b>, crossing lines pattern.
	      </li>
	      <li>
	        <b>BDiagPattern</b>, diagonal lines (directed / ) pattern.
	      </li>
	      <li>
	        <b>FDiagPattern</b>, diagonal lines (directed \ ) pattern.
	      </li>
	      <li>
	        <b>DiagCrossPattern</b>, diagonal crossing lines pattern.
	      </li>
	    </ul>
	    Values are case sensitive. If <i>bgpattern</i> isn't defined for a
	    table and <i>bgcolor</i> is used, it will default to
	    <b>SolidPattern</b>
	  </li>
	  <li>
	    <i>cellpadding</i>: number of pixels to leave between the
	    invisible cell border and cell's content. For instance, if a cells
	    top-left corner is at (16, 16) on the screen and cellspacing="32",
	    the first object in the cell will be drawn at (48, 48)
	  </li>
	  <li>
	    <i>width</i>: the width of this cell. If the renderer decided the
	    defined width is too large for the current table (i.e., the
	    &lt;td&gt; width is larger than the &lt;table&gt; width or than
	    the total slide width), a default width will be decided upon.
	    <br>
	    Possible table cell widths are in pixels or percentage of the
	    &lt;table&gt;/&lt;tr&gt; width.
	  </li>
	  <li>
	    <i>border</i>: border size in pixels to draw around the cell.
	  </li>
	  <li>
	    <i>bordercolor/bordercolour</i>: colour to use for <i>border</i>
	  </li>
	</ul>
	"""

	def __init__( self, *args ):
		"""
		Initiate the container, contents, and properties.

		-*args, arguments for the PresentationObject constructor.
		"""

		apply( PresentationObject.__init__, (self,) + args )

		#
		# If bgcolor is defined in the parent <tr>, copy it here.
		#
		container = self.getContainer()
		if container.hasProperty("bgcolor"):
			self.setProperty( "bgcolor",
			                  container.getProperty("bgcolor") )

	def render( self, app, x, y ):
		"""
		Draw the contents of this table cell to the app's QCanvas.

		-app, SlideApplication object
		-x, x coordinate to start drawing at
		-y, y coordinate to start drawing at

		Returns x, y coordinates where the rendering left off.
		"""

		self.setCoords( x, y )

		initX = x
		initY = y

		#
		# Set the left and right bounds between which objects can be
		# drawn on the canvas.
		#
		x = x + self.getProperty( "cellpadding" )
		self.setProperty( "marginleft", x )
		self.setProperty( "marginright",
		                  app.getWidth()   - \
		                  (x + self.getWidth()) + \
		                  self.getProperty("cellpadding") )

		origY = y
		y = y + self.getProperty( "cellpadding" )

		#
		# Draw PresentationObjects into this table cell.
		#
		for content in self.getContents():
			if isinstance(content, PresentationObject):
				x, y = content.render( app, x, y )
			else:
				#
				# Replace string objects with <font> instances.
				# This is easier than extending this class with
				# the font class and calling font.render(),
				# etc.
				#
				from font import font
				text = font( self,
				             [content],
				             self.getProperties() )
				i = self.getContents().index( content )
				self.getContents()[i] = text
				x, y = text.render( app, x, y )

		y = y + self.getProperty( "cellpadding" )

		#
		# Set the height of this cell. If no content was drawn in it
		# and there's no cellpadding, leave enough space on the y axis
		# to prevent 0 height cells.
		#
		height = y - origY + self.getSlide().getRenderHeight()
		if height == 0:
			from font import font
			height = height + \
			         font( self ).getFontHeight( app.getHeight() )
		self.setHeight( height )

		self.getSlide().setFontHeight(0)

		return x, y

	def showBackground( self ):
		"""
		Display the background image, if one has been set.
		"""

		#
		# Display a background image, if needed.
		#
		if not self.hasProperty("background") and \
		   not self.getContainer().hasProperty("background"):
			return failure

		#
		# Remove any existing background image.
		#
		try:
			self.__bg.setCanvas( QCanvas() )
		except AttributeError:
			#
			# Get the full path to the image filename.
			#
			bgPath = self.getProperty( "background" )
			if not os.path.isabs(bgPath):
				dir = self.getSlideshow().getDirName()
				bgPath = os.path.join( dir, bgPath )
			bgImage = QImage( bgPath )
			if bgImage.isNull():
				return failure

			self.__bgPixmap = QPixmap()
			self.__bgPixmap.convertFromImage( bgImage )

			color = QColor( self.getProperty("bgcolor") )
			self.__bgBrush = QBrush( color )
			self.__bgBrush.setPixmap( self.__bgPixmap )

		canvas = self.getSlide().getCanvas()
		self.__bg = QCanvasRectangle( self.x(),
		                              self.y(),
		                              self.getWidth(),
		                              self.getHeight(),
		                              canvas )
		self.__bg.setBrush( self.__bgBrush )

		if self.isAnimated():
			self.__bg.hide()
		else:
			self.__bg.show()

		self.increaseZ()

		return success

	def showBackgroundColor( self, ):
		"""
		Display the background color, if one has been set.
		"""

		if not self.hasProperty("bgcolor") and \
		   not self.getContainer().hasProperty("bgcolor"):
			return

		#
		# Remove any existing background colour rectangle.
		#
		try:
			self.__bgColor.setCanvas( QCanvas() )
		except AttributeError:
			pattern = self.getProperty( "bgpattern" )

			#
			# Convert bgpattern string to the QBrush constant.
			#
			# Check user doesn't try an option that calls a
			# function or something CREZY/INSANE. DiagCrossPattern
			# is the constant with the longest string length.
			#
			if len(pattern) == 0                      or \
			   len(pattern) > len("DiagCrossPattern") or \
			   re.search("exec",  pattern) != None    or \
			   re.search("\(|\)", pattern) != None:
				pattern = QBrush.SolidPattern
			else:
				try:
					pattern = eval( "QBrush.%s" % pattern )
				except:
					pattern = Qt.SolidPattern

			color = QColor( self.getProperty("bgcolor") )
			self.__brush = QBrush( color )
			self.__brush.setStyle( pattern )

		canvas = self.getSlide().getCanvas()
		self.__bgColor = QCanvasRectangle( self.x(),
		                                   self.y(),
		                                   self.getWidth(),
		                                   self.getHeight(),
		                                   canvas )
		self.__bgColor.setBrush( self.__brush )

		if self.isAnimated():
			self.__bgColor.hide()