# -*- coding: iso-8859-15 -*-


# Glasnost
# By: Odile Bénassy <obenassy@entrouvert.com>
#     Romain Chantereau <rchantereau@entrouvert.com>
#     Nicolas Clapiès <nclapies@easter-eggs.org>
#     Pierre-Antoine Dejace <padejace@entrouvert.be>
#     Thierry Dulieu <tdulieu@easter-eggs.com>
#     Florent Monnier <monnier@codelutin.com>
#     Cédric Musso <cmusso@easter-eggs.org>
#     Frédéric Péters <fpeters@entrouvert.be>
#     Benjamin Poussin <poussin@codelutin.com>
#     Emmanuel Raviart <eraviart@entrouvert.com>
#     Sébastien Régnier <regnier@codelutin.com>
#     Emmanuel Saracco <esaracco@easter-eggs.com>
#
# Copyright (C) 2000, 2001 Easter-eggs & Emmanuel Raviart
# Copyright (C) 2002 Odile Bénassy, Code Lutin, Thierry Dulieu, Easter-eggs,
#     Entr'ouvert, Frédéric Péters, Benjamin Poussin, Emmanuel Raviart,
#     Emmanuel Saracco & Théridion
# Copyright (C) 2003 Odile Bénassy, Romain Chantereau, Nicolas Clapiès,
#     Code Lutin, Pierre-Antoine Dejace, Thierry Dulieu, Easter-eggs,
#     Entr'ouvert, Florent Monnier, Cédric Musso, Ouvaton, Frédéric Péters,
#     Benjamin Poussin, Rodolphe Quiédeville, Emmanuel Raviart, Sébastien
#     Régnier, Emmanuel Saracco, Théridion & Vecam
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

# Some part inspired by code Copyright (C) 1998 by Michael A. Miller


__doc__ = """Glasnost Graphing Module"""

__version__ = '$Revision$'[11:-2]


import sys
import math
try:
    import libplot
except ImportError:
    libplot = None
import tempfile
from cStringIO import StringIO

import glasnost.common.context as context


### Piecharts ###

class Slice:
    def __init__(self, t, v):
        self.text = t;            # label for the slice
        self.value = v            # value for the slice
    def __repr__(self):
        return '<Slice %s, %.2f>' % (repr(self.text), self.value)

def X(radius, angle):
    x = math.cos(RAD(angle)) * radius
    return x

def Y(radius, angle):
    y = math.sin(RAD(angle)) * radius
    return y

def RAD(angle):
    a = angle / 180.0 * math.pi
    return a


colortable = [ "red", "blue", "green", "yellow", "brown", 
               "coral", "magenta", "cyan", "seagreen3" ]

# Color in which the separating lines and the circle are drawn
LINECOLOR = "black"

# LINEWIDTH_LINES is for the separating lines and the circle
# -1 means default 
LINEWIDTH_LINES = -1

def getPie(slices):
    if not libplot:
        raise 'Libplot not available'

    stream = StringIO()
    stream = tempfile.TemporaryFile('w+')
    params = { 'BITMAPSIZE': '400x400',
                'TRANSPARENT_COLOR': 'white'}
    plot = libplot.Plotter(type = 'PNG', outfile=stream, params=params)

    # Sum up values
    sum = 0.0
    for s in slices:
        sum = sum + s.value
    if plot.openpl() < 0:
        raise Exception('Unable to open plotter')

    if plot.fspace(-1.2,-1.2,1.2,1.2):
        raise Exception('Error in fspace()')
    #if plot.space(-1.2,-1.2,1.2,1.2):
    #    raise Exception('Error in space()')

    plot.pencolorname(LINECOLOR)
    plot.ffontsize(0.08)

    # and now for the slices
    angle = 0.0
    distance = 0.0
    r = 1.0
    
    plot.savestate()
    plot.joinmod("round")
    
    plot.filltype(1)
    plot.flinewidth(LINEWIDTH_LINES)
    plot.pencolorname(LINECOLOR)
    color = 0
    for s in slices:
        # draw one path for every slice
        distance = ( s.value / sum ) * 360.0
        plot.fillcolorname(colortable[color])
                                
        plot.fmove(0,0)          # start at center...
        plot.fcont(X(r,angle), Y(r,angle))
        if distance > 179.0:
            # we need to draw a semicircle first
            # we have to be sure to draw counterclockwise (180 wouldn`t work 
            # in all cases)
            plot.farc( 0, 0, X(r,angle), Y(r,angle), X(r,angle+179), Y(r,angle+179) )
            angle = angle + 179.0
            distance = distance = 179.0

        plot.farc( 0, 0, X(r,angle), Y(r,angle), 
                  X(r,angle+distance), Y(r,angle+distance))
        plot.fcont(0,0)           # return to center
        plot.endpath()            # not really necessary, but intuitive
        
        angle = angle + distance # log fraction of circle already drawn
        
        color = color + 1       # next color for next slice
        if color >= len(colortable):
            color = 0

        # the closing circle at the end
        plot.filltype(0)
        plot.fcircle(0.,0.,r)

        # one point in the middle
        plot.colorname(LINECOLOR)
        plot.filltype(1)
        plot.fpoint(0,0)
                                        
        plot.endpath()

    # and now for the text
    angle = 0
    distance = 0
    r = 0.7

    plot.savestate();

    for s in slices:
        distance = ( s.value / sum ) * 360.0
        # calculate the position
        place = angle + 0.5 * distance
        # and the alignment
        if place < 180:
            v = 'b'
        else:
            v = 't';
        if place < 90 or place > 270:
            h = 'l'
        else:
            h = 'r'
        plot.fmove(X(r,place), Y(r,place))
        plot.alabel(ord(h), ord(v), '%s (%.2f%%)' % (s.text, s.value/sum*100))
        
        angle = angle + distance
                                        
        plot.endpath()

    # end plot sesssion
    plot.closepl()

    stream.seek(0)
    return stream.read()

