#!/usr/bin/env python
"""
A python module with logging to provide a display for animations.

Metadata:

  - Author:    W.S.Kendall
  - Copyright: opensource (c) W.S.Kendall 2008
  - Date:      2008-07-04
  - URL:       http://www.wilfridkendall.co.uk
  - Generator: '/home/wilfrid/lib/python/generate.py' version 1.18.


Command-line options::

  usage: %prog [options] arguments
    --logging=LOGGING:	   logging verbosity level.

Notes:
 - values for 'logging' option:
 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'
 (decreasing level of verbosity), with 'WARNING' as default.

"""
__RCSID__ = '$Revision: 1.3 $ $Date: 2008/07/08 05:56:03 $'


# \section{Definitions}
# We need the logging module regardless of whether the #logging# option
# is deployed, since #logging.info# calls are scattered through the text.
import logging, math
from PIL import Image, ImageTk, ImageEnhance
import Tkinter as Tk

BOLD = ('Helvetica', 10, 'bold')
ITALICS = ('Helvetica', 10, 'bold italic')


#\section{Exceptions}
class Error(Exception):
    """
    Generic exception to be raised by this module.
    """


# \section{Classes}
class Display2(object):
	"""
	Create and decorate a Canvas for display.
	"""
	def __init__(self, root, \
		xlo=0, xhi=1, ylo=0, yhi=10, border=0.05, \
		width=832, height=666, image=None, **kw):
		
		self.frame = Tk.Frame(root)
		self.frame.pack()
		self.canvas = Tk.Canvas(self.frame, \
			width=width, height=height, **kw)
		self.canvas.pack(side=Tk.LEFT)
		
		self.buttonframe = Tk.Frame(self.frame)
		self.buttonframe.pack(side=Tk.RIGHT, fill=Tk.Y)
		self.button(text='QUIT', font=BOLD, foreground='red', \
				command=root.destroy, side=Tk.BOTTOM)
		
		# Constants for conversion from user units to drawing units.
                self.xm = (1 - 2 * border) * width / float(xhi - xlo)
                self.xlo = border * width - self.xm * xlo

                self.ym = - (1 - 2 * border) * height / float(yhi - ylo)
                self.ylo = (1 - border) * height - self.ym * ylo
		
		xbit, ybit = 0.02 * (xhi - xlo), 0.02 * (yhi - ylo)
		if not image:
		    self.box(xlo - xbit, ylo - ybit, xhi + xbit, yhi + ybit, \
				 outline='lightblue', fill='white')
		else:
		    im = Image.open(image).convert("RGBA")
		    enh = ImageEnhance.Contrast(im)
		    im = enh.enhance(0.5)
		    im.thumbnail((5*128, 5*128))
		    self.imt = ImageTk.PhotoImage(im)
		    self.canvas.create_image(10, 10, anchor=Tk.NW, image=self.imt)
		
		self.axis(xlo, ylo, xhi - xlo, xalign=True)
		self.axis(xlo, ylo, yhi - ylo, xalign=False)
		
	def button(self, side=Tk.TOP, **kw):
		"""
		Add a button.
		"""
		Tk.Button(self.buttonframe, **kw).pack(side=side, fill=Tk.X)
		
	def convert(self, x, y):
		"""
		Convert from user units to to drawing units.
		"""
		return self.xlo + self.xm * x, self.ylo + self.ym * y
	
	def line(self, xlo, ylo, xhi, yhi, **kw):
		"""
		Draw a line in user units.
		"""
		xlo, ylo = self.convert(xlo, ylo)
		xhi, yhi = self.convert(xhi, yhi)
		self.canvas.create_line(xlo, ylo, xhi, yhi, **kw)
	
	def box(self, xlo, ylo, xhi, yhi, **kw):
		"""
		Draw a box.
		"""
		xlo, ylo = self.convert(xlo, ylo)
		xhi, yhi = self.convert(xhi, yhi)
		self.canvas.create_polygon(xlo, ylo, xlo, yhi, xhi, yhi, xhi, ylo, **kw)
		
	def axis(self, xlo, ylo, ell, xalign=True, **kw):
		"""
		Draw an axis.
		"""
		if xalign:
			xhi, yhi = xlo + ell, ylo
		else:
			xhi, yhi = xlo, ylo + ell
		self.line(xlo, ylo, xhi, yhi, **kw)
		
	def dot(self, loc, width=3, **kw):
		"""
		Draw a dot.
		"""
		x, y = self.convert(*loc)
		self.canvas.create_oval(x - width, y - width, \
					    x + width, y + width, **kw)
		
	def write(self, txt, x, y, **kw):
		"""
		Write some text in specified position (user coordinates).
		"""
		x, y = self.convert(x, y)
		self.canvas.create_text(x, y, text=txt, **kw)


# \section{Functions}
def main(opt, arguments):
    """
    The action of the module as script should be concentrated here!
    """
    logging.info('Entering main function')
    root = Tk.Tk()
    display = Display2(root, xlo=0, xhi=4, ylo=0, yhi=10)
    display.dot((0, 0), fill='red')
    for yinc in range(1, 11):
	    display.axis(0, yinc, 4, fill='lightgray')
	    display.dot((0, yinc))
    for xinc in range(1, 5):
	    display.axis(xinc, 0, 10, fill='skyblue', xalign=False)
	    display.dot((xinc, 0))

    root.mainloop()



# \section{Main script}
if __name__ == '__main__':
    import optionparse
    option, args = optionparse.parse(__doc__, version=__RCSID__)

    if option.logging is not None:
	logging.basicConfig(level=logging.__dict__[option.logging])
	logging.info('Logging level %s' % option.logging)


    # The action of the module as script should be concentrated
    # in the following function, to facilitate profiling.
    main(option, args)


    logging.info('Finishing')
    raise SystemExit


# \newpage \scriptsize
# \begin{multicols}{2}
# \section{History}
# \text{ }
#\\ $Log: display2.py,v $
#\\ Revision 1.3  2008/07/08 05:56:03  wskendall
#\\ Checkpoint before trying to fix transformations.
#\\
#\\ Revision 1.2  2008/07/05 15:26:01  wskendall
#\\ Aded photo background option.
#\\
#\\ Revision 1.1  2008/07/05 10:33:39  wskendall
#\\ Initial revision
#\\
#
# \end{multicols}

'$Id: display2.py,v 1.3 2008/07/08 05:56:03 wskendall Development wskendall $'
