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