1 |
bh |
2074 |
# Copyright (c) 2001, 2002, 2003 by Intevation GmbH |
2 |
|
|
# Authors: |
3 |
|
|
# Markus Rechtien <[email protected]> |
4 |
|
|
# |
5 |
|
|
# This program is free software under the GPL (>=v2) |
6 |
|
|
# Read the file COPYING coming with Thuban for details. |
7 |
|
|
|
8 |
|
|
__version__ = "$Revision$" |
9 |
|
|
# $Source$ |
10 |
|
|
# $Id$ |
11 |
|
|
|
12 |
|
|
|
13 |
|
|
""" |
14 |
|
|
Write a basic map legend in svg format. |
15 |
|
|
""" |
16 |
|
|
|
17 |
|
|
|
18 |
dpinte |
2721 |
# Needed wx.-toolkit classes |
19 |
|
|
import wx |
20 |
bh |
2074 |
|
21 |
|
|
# We need os.path |
22 |
|
|
import os |
23 |
|
|
|
24 |
|
|
# Use _() already now for all strings that may later be translated |
25 |
|
|
from Thuban import _ |
26 |
|
|
|
27 |
|
|
# Color related classes defined in the thuban model |
28 |
|
|
from Thuban.Model.color import Transparent, Color, Black |
29 |
|
|
|
30 |
|
|
# Different shape types |
31 |
|
|
from Thuban.Model.data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \ |
32 |
|
|
SHAPETYPE_POINT, RAW_SHAPEFILE |
33 |
|
|
|
34 |
|
|
# Import SVG related classes |
35 |
|
|
from svgmapwriter import SVGRenderer, VirtualDC, TRANSPARENT_PEN, \ |
36 |
|
|
TRANSPARENT_BRUSH, SOLID, Pen, Brush, Point |
37 |
|
|
|
38 |
|
|
|
39 |
|
|
BLACK_PEN = Pen() |
40 |
|
|
|
41 |
|
|
class SVGMapLegend(SVGRenderer): |
42 |
|
|
"""Class to render a basic map legend. |
43 |
|
|
|
44 |
|
|
""" |
45 |
|
|
def __init__(self, dc, map=None, scale=(1.0), offset=(0,0), |
46 |
|
|
region=(0,0,0,0), resolution = 72.0, |
47 |
|
|
honor_visibility = 1, destination_region = (0,0,0,0)): |
48 |
|
|
SVGRenderer.__init__(self, dc, map, scale, offset, region, |
49 |
|
|
resolution, honor_visibility) |
50 |
|
|
self.destination_region = destination_region |
51 |
|
|
self.factor = 1.0 |
52 |
|
|
|
53 |
|
|
def RenderLegend(self, layers): |
54 |
|
|
"""Render the legend on the Map.""" |
55 |
|
|
dc = self.dc |
56 |
|
|
dc.SetPen(BLACK_PEN) |
57 |
|
|
dc.SetBrush(TRANSPARENT_BRUSH) |
58 |
|
|
# Dimension stuff |
59 |
|
|
width, height = dc.GetSizeTuple() |
60 |
|
|
mminx, mminy, mmaxx, mmaxy = self.destination_region |
61 |
|
|
textwidth, textheight = dc.GetTextExtent("0") |
62 |
|
|
iconwidth = iconheight = textheight |
63 |
|
|
stepy = 12 |
64 |
|
|
dx = 12 |
65 |
|
|
posx = mmaxx + 20 + 10 # 20 pix distance mapframe/legend frame, |
66 |
|
|
# 10 pix inside legend frame |
67 |
|
|
posy = mminy + 20 # 20 pix inside legend frame |
68 |
|
|
# |
69 |
|
|
self.dc.BeginGroup(meta={'Object':'legend', }) |
70 |
|
|
# Render the legend |
71 |
|
|
dc.SetTextForeground(Black) |
72 |
|
|
if layers: |
73 |
|
|
layers.reverse() |
74 |
|
|
for l in layers: |
75 |
|
|
if l.Visible(): |
76 |
|
|
# Render title |
77 |
|
|
dc.DrawText(l.Title(), posx, posy) |
78 |
|
|
posy+=stepy |
79 |
|
|
if l.HasClassification(): |
80 |
|
|
# Render classification |
81 |
|
|
clazz = l.GetClassification() |
82 |
|
|
shapeType = l.ShapeType() |
83 |
|
|
for g in clazz: |
84 |
|
|
if g.IsVisible(): |
85 |
dpinte |
2721 |
self.Draw(dc, wx.Rect(posx+dx, |
86 |
bh |
2074 |
posy-iconheight+2, |
87 |
|
|
iconwidth, iconheight), |
88 |
|
|
g.GetProperties(), shapeType) |
89 |
|
|
dc.DrawText(g.GetDisplayText(), |
90 |
|
|
posx+2*dx+iconwidth, posy) |
91 |
|
|
posy+=stepy |
92 |
|
|
posy+=10 |
93 |
|
|
self.dc.EndGroup() |
94 |
|
|
|
95 |
|
|
def Draw(self, dc, rect, prop, shapeType): |
96 |
|
|
'''Draw little icon for a shape depending on given properties.''' |
97 |
|
|
x = rect.GetX() |
98 |
|
|
y = rect.GetY() |
99 |
|
|
w = rect.GetWidth() |
100 |
|
|
h = rect.GetHeight() |
101 |
|
|
|
102 |
|
|
pen, brush = self.tools_for_property(prop) |
103 |
|
|
dc.SetPen(pen) |
104 |
|
|
dc.SetBrush(brush) |
105 |
|
|
|
106 |
|
|
if shapeType == SHAPETYPE_ARC: |
107 |
|
|
dc.DrawSpline([Point(x, y + h), |
108 |
|
|
Point(x + w/2, y + h/4), |
109 |
|
|
Point(x + w/2, y + h/4*3), |
110 |
|
|
Point(x + w, y)]) |
111 |
|
|
|
112 |
|
|
elif shapeType == SHAPETYPE_POINT: |
113 |
|
|
dc.DrawCircle(x + w/2, y + h/2, |
114 |
|
|
(min(w, h) - prop.GetLineWidth())/2) |
115 |
|
|
|
116 |
|
|
elif shapeType == SHAPETYPE_POLYGON: |
117 |
|
|
dc.DrawRectangle(x, y, w, h) |
118 |
|
|
|
119 |
|
|
|
120 |
|
|
def write_legend(context): |
121 |
bernhard |
2388 |
"""Export the data depending on the set properties. |
122 |
|
|
|
123 |
|
|
This is the main export function. |
124 |
|
|
""" |
125 |
bh |
2074 |
canvas = context.mainwindow.canvas |
126 |
|
|
file = None |
127 |
|
|
map = canvas.Map() |
128 |
|
|
# |
129 |
|
|
if hasattr(canvas, "export_path"): |
130 |
|
|
export_path = canvas.export_path |
131 |
|
|
else: |
132 |
|
|
export_path="." |
133 |
|
|
# Get the file the session shall be written to |
134 |
dpinte |
2721 |
dlg = wx.FileDialog(canvas, _("Write SVG"), export_path, "", |
135 |
bh |
2074 |
"Scalable Vector Graphics (*.svg)|*.svg", |
136 |
dpinte |
2721 |
wx.SAVE|wx.OVERWRITE_PROMPT) |
137 |
bh |
2074 |
# |
138 |
|
|
response = dlg.ShowModal() |
139 |
dpinte |
2721 |
if response == wx.ID_OK: |
140 |
bh |
2074 |
file = dlg.GetPath() |
141 |
|
|
else: # Do nothing if choice was interrupted. |
142 |
|
|
return 0 |
143 |
|
|
|
144 |
|
|
# If the user selected a file |
145 |
|
|
if file and map is not None: |
146 |
|
|
canvas.export_path = os.path.dirname(file) |
147 |
|
|
width, height = canvas.GetSizeTuple() |
148 |
|
|
llx, lly = canvas.win_to_proj(0, height) |
149 |
|
|
urx, ury = canvas.win_to_proj(width, 0) |
150 |
|
|
mapwidth, mapheight = ((urx - llx), (ury - lly)) |
151 |
|
|
# |
152 |
|
|
selected_layer = map.Layers() |
153 |
|
|
dc = VirtualDC(file, (mapwidth, mapheight, )) |
154 |
|
|
dc.BeginExport() |
155 |
|
|
# |
156 |
|
|
renderer = SVGMapLegend(dc) |
157 |
|
|
renderer.RenderLegend(selected_layer) |
158 |
|
|
# |
159 |
|
|
dc.EndExport() |
160 |
|
|
|
161 |
|
|
|
162 |
|
|
# Thuban has named commands which can be registered in the central |
163 |
|
|
# instance registry. |
164 |
|
|
from Thuban.UI.command import registry, Command |
165 |
|
|
|
166 |
|
|
# The instance of the main menu of the Thuban application |
167 |
|
|
# See Thuban/UI/menu.py for the API of the Menu class |
168 |
|
|
from Thuban.UI.mainwindow import main_menu |
169 |
|
|
|
170 |
|
|
# create a new command and register it |
171 |
|
|
registry.Add(Command('write_legend', _('Write SVG Legend'), write_legend, |
172 |
|
|
helptext = _('Write a basic Legend for the map.'))) |
173 |
|
|
|
174 |
bernhard |
2482 |
# find the menu we want to be in (create it anew if not found) |
175 |
|
|
menu = main_menu.FindOrInsertMenu('extensions', _('E&xtensions')) |
176 |
jan |
2417 |
|
177 |
bh |
2074 |
# finally bind the new command with an entry in the extensions menu |
178 |
bernhard |
2482 |
menu.InsertItem('write_legend') |