# Copyright (c) 2001, 2002, 2003 by Intevation GmbH
# Authors:
#     Markus Rechtien <markus@intevation.de>
#
# This program is free software under the GPL (>=v2)
# Read the file COPYING coming with Thuban for details.

__version__ = "$Revision: 2817 $"
# $Source$
# $Id: maplegend.py 2817 2008-01-27 00:01:32Z bernhard $


"""
Write a basic map legend in svg format.
"""


# Needed wx-toolkit classes
from wx import FileDialog, SAVE, OVERWRITE_PROMPT, \
        ID_OK, Rect

# We need os.path
import os

# Use _() already now for all strings that may later be translated
from Thuban import _

# Color related classes defined in the thuban model
from Thuban.Model.color import Transparent, Color, Black

# Different shape types
from Thuban.Model.data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \
    SHAPETYPE_POINT, RAW_SHAPEFILE

from Thuban.UI import internal_from_wxstring

# Import SVG related classes
from svgmapwriter import SVGRenderer, VirtualDC, TRANSPARENT_PEN, \
        TRANSPARENT_BRUSH, SOLID, Pen, Brush, Point


BLACK_PEN = Pen()

class SVGMapLegend(SVGRenderer):
    """Class to render a basic map legend.
    
    """
    def __init__(self, dc, map=None, scale=(1.0), offset=(0,0), 
            region=(0,0,0,0), resolution = 72.0, 
            honor_visibility = 1, destination_region = (0,0,0,0)):
        SVGRenderer.__init__(self, dc, map, scale, offset, region,
                resolution, honor_visibility)
        self.destination_region = destination_region
        self.factor = 1.0
    
    def RenderLegend(self, layers):
        """Render the legend on the Map."""
        dc = self.dc
        dc.SetPen(BLACK_PEN)
        dc.SetBrush(TRANSPARENT_BRUSH)
        # Dimension stuff
        width, height = dc.GetSizeTuple()
        mminx, mminy, mmaxx, mmaxy = self.destination_region
        textwidth, textheight = dc.GetTextExtent("0")
        iconwidth  = iconheight = textheight
        stepy = 12
        dx = 12
        posx = mmaxx + 20 + 10  # 20 pix distance mapframe/legend frame,
                                # 10 pix inside legend frame
        posy = mminy + 20       # 20 pix inside legend frame
        #
        self.dc.BeginGroup(meta={'Object':'legend', })
        # Render the legend
        dc.SetTextForeground(Black)
        if layers:
            layers.reverse()
            for l in layers:
                if l.Visible():
                    # Render title
                    dc.DrawText(l.Title(), posx, posy)
                    posy+=stepy
                    if l.HasClassification():
                        # Render classification
                        clazz = l.GetClassification()
                        shapeType = l.ShapeType()
                        for g in clazz:
                            if g.IsVisible():
                                self.Draw(dc, Rect(posx+dx, 
                                        posy-iconheight+2,
                                        iconwidth, iconheight),
                                        g.GetProperties(), shapeType)
                                dc.DrawText(g.GetDisplayText(),
                                        posx+2*dx+iconwidth, posy)
                                posy+=stepy
                    posy+=10
        self.dc.EndGroup()

    def Draw(self, dc, rect, prop, shapeType):
        '''Draw little icon for a shape depending on given properties.'''
        x = rect.GetX()
        y = rect.GetY()
        w = rect.GetWidth()
        h = rect.GetHeight()

        pen, brush = self.tools_for_property(prop)
        dc.SetPen(pen)
        dc.SetBrush(brush)

        if shapeType == SHAPETYPE_ARC:
            dc.DrawSpline([Point(x, y + h),
                           Point(x + w/2, y + h/4),
                           Point(x + w/2, y + h/4*3),
                           Point(x + w, y)])

        elif shapeType == SHAPETYPE_POINT:
            dc.DrawCircle(x + w/2, y + h/2,
                          (min(w, h) - prop.GetLineWidth())/2)
                          
        elif shapeType == SHAPETYPE_POLYGON:
            dc.DrawRectangle(x, y, w, h)


def write_legend(context):
    """Export the data depending on the set properties.

    This is the main export function.
    """
    canvas = context.mainwindow.canvas
    file = None
    map = canvas.Map()
    #
    if hasattr(canvas, "export_path"):
        export_path = canvas.export_path
    else:
        export_path="."
    # Get the file the session shall be written to
    dlg = FileDialog(canvas, _("Write SVG"), export_path, "", 
            "Scalable Vector Graphics (*.svg)|*.svg", 
            SAVE|OVERWRITE_PROMPT)
    #
    response = dlg.ShowModal()
    if response == ID_OK:
        file = internal_from_wxstring(dlg.GetPath())
    else: # Do nothing if choice was interrupted.
        return 0
        
    # If the user selected a file
    if file and map is not None:
        canvas.export_path = os.path.dirname(file)
        width, height = canvas.GetSizeTuple()
        llx, lly = canvas.win_to_proj(0, height)
        urx, ury = canvas.win_to_proj(width, 0)
        mapwidth, mapheight = ((urx - llx), (ury - lly))
        # 
        selected_layer = map.Layers()
        dc = VirtualDC(file, (mapwidth, mapheight, ))
        dc.BeginExport()
        #
        renderer = SVGMapLegend(dc)
        renderer.RenderLegend(selected_layer)
        #
        dc.EndExport()

    
# Thuban has named commands which can be registered in the central
# instance registry.
from Thuban.UI.command import registry, Command

# The instance of the main menu of the Thuban application
# See Thuban/UI/menu.py for the API of the Menu class
from Thuban.UI.mainwindow import main_menu

# create a new command and register it
registry.Add(Command('write_legend', _('Write SVG Legend'), write_legend,
                     helptext = _('Write a basic Legend for the map.')))

# find the menu we want to be in (create it anew if not found)
menu = main_menu.FindOrInsertMenu('extensions', _('E&xtensions'))

# finally bind the new command with an entry in the extensions menu
menu.InsertItem('write_legend')
