2 |
# Authors: |
# Authors: |
3 |
# Bernhard Herzog <[email protected]> |
# Bernhard Herzog <[email protected]> |
4 |
# Jonathan Coles <[email protected]> |
# Jonathan Coles <[email protected]> |
5 |
|
# Frank Koormann <[email protected]> |
6 |
# |
# |
7 |
# This program is free software under the GPL (>=v2) |
# This program is free software under the GPL (>=v2) |
8 |
# Read the file COPYING coming with Thuban for details. |
# Read the file COPYING coming with Thuban for details. |
9 |
|
|
10 |
__version__ = "$Revision$" |
__version__ = "$Revision$" |
11 |
|
|
12 |
from wxPython.wx import wxPoint, wxPen, wxBrush, wxFont, \ |
from Thuban import _ |
13 |
wxTRANSPARENT_PEN, wxTRANSPARENT_BRUSH, \ |
|
14 |
wxBLACK, wxSOLID, wxCROSS_HATCH, wxSWISS, wxNORMAL |
from wxPython.wx import wxMemoryDC, wxEmptyBitmap, \ |
15 |
|
wxPoint, wxRect, wxPen, wxBrush, wxFont, \ |
16 |
|
wxTRANSPARENT_PEN, wxTRANSPARENT_BRUSH, \ |
17 |
|
wxBLACK_PEN, wxRED_PEN, wxBLACK, wxSOLID, wxCROSS_HATCH, wxSWISS, wxNORMAL |
18 |
|
|
19 |
from wxproj import draw_polygon_shape, draw_polygon_init |
from wxproj import draw_polygon_shape, draw_polygon_init |
20 |
|
|
21 |
from Thuban import _ |
from Thuban.UI.common import Color2wxColour |
22 |
from Thuban.UI.common import * |
from Thuban.UI.classifier import ClassDataPreviewer |
23 |
|
from Thuban.UI.scalebar import ScaleBar |
24 |
|
|
25 |
from Thuban.Model.layer import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \ |
from Thuban.Model.layer import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \ |
26 |
SHAPETYPE_POINT |
SHAPETYPE_POINT |
105 |
if field is None: |
if field is None: |
106 |
group = defaultGroup |
group = defaultGroup |
107 |
else: |
else: |
108 |
record = layer.table.read_record(i) |
record = layer.table.ReadRowAsDict(i) |
109 |
assert record is not None |
assert record is not None |
110 |
group = lc.FindGroup(record[field]) |
group = lc.FindGroup(record[field]) |
111 |
|
|
330 |
return layer.ShapesInRegion((left, bottom, right, top)) |
return layer.ShapesInRegion((left, bottom, right, top)) |
331 |
|
|
332 |
|
|
333 |
class PrinterRender(MapRenderer): |
class ExportRenderer(ScreenRenderer): |
334 |
|
|
335 |
# When printing we want to see all layers |
honor_visibility = 1 |
|
honor_visibility = 0 |
|
|
|
|
|
RenderMap = MapRenderer.render_map |
|
336 |
|
|
337 |
|
def RenderMap(self, map, region, mapregion, |
338 |
|
selected_layer, selected_shapes ): |
339 |
|
"""Render the map. |
340 |
|
|
341 |
|
The rendering device has been specified during initialisation. |
342 |
|
The device border distance was set in Thuban.UI.view.OutputTranform(). |
343 |
|
|
344 |
|
RenderMap renders a frame set (one page frame, one around |
345 |
|
legend/scalebar and one around the map), the map, the legend and the |
346 |
|
scalebar on the given DC. The map is rendered with the region displayed |
347 |
|
in the canvas view, centered on the area available for map display. |
348 |
|
""" |
349 |
|
|
350 |
|
self.update_region = region |
351 |
|
self.selected_layer = selected_layer |
352 |
|
self.selected_shapes = selected_shapes |
353 |
|
|
354 |
|
# Get some dimensions |
355 |
|
llx, lly, urx, ury = region |
356 |
|
self.mapregion = mapregion |
357 |
|
mminx, mminy, mmaxx, mmaxy = self.mapregion |
358 |
|
|
359 |
|
# Manipulate the offset to position the map |
360 |
|
offx, offy = self.offset |
361 |
|
# 1. Shift to corner of map drawing area |
362 |
|
offx = offx + mminx |
363 |
|
offy = offy + mminy |
364 |
|
|
365 |
|
# 2. Center the map on the map drawing area: |
366 |
|
# region identifies the region on the canvas view: |
367 |
|
# center of map drawing area - half the size of region: rendering origin |
368 |
|
self.shiftx = (mmaxx - mminx)*0.5 - (urx - llx)*0.5 |
369 |
|
self.shifty = (mmaxy - mminy)*0.5 - (ury - lly)*0.5 |
370 |
|
|
371 |
|
self.offset = (offx+self.shiftx, offy+self.shifty) |
372 |
|
|
373 |
|
# Draw the map |
374 |
|
self.dc.BeginDrawing() |
375 |
|
self.dc.DestroyClippingRegion() |
376 |
|
self.dc.SetClippingRegion(mminx+self.shiftx, mminy+self.shifty, |
377 |
|
urx, ury) |
378 |
|
self.render_map(map) |
379 |
|
self.dc.EndDrawing() |
380 |
|
|
381 |
|
# Draw the rest (frames, legend, scalebar) |
382 |
|
self.dc.BeginDrawing() |
383 |
|
self.dc.DestroyClippingRegion() |
384 |
|
|
385 |
|
# Force the font for Legend drawing |
386 |
|
font = wxFont(self.resolution * 10, wxSWISS, wxNORMAL, wxNORMAL) |
387 |
|
self.dc.SetFont(font) |
388 |
|
|
389 |
|
self.render_frame(region) |
390 |
|
self.render_legend(map) |
391 |
|
self.render_scalebar(map) |
392 |
|
self.dc.EndDrawing() |
393 |
|
|
394 |
|
def render_frame(self, region): |
395 |
|
"""Render the frames for map and legend/scalebar.""" |
396 |
|
|
397 |
|
dc = self.dc |
398 |
|
dc.SetPen(wxBLACK_PEN) |
399 |
|
dc.SetBrush(wxTRANSPARENT_BRUSH) |
400 |
|
|
401 |
|
# Dimension stuff |
402 |
|
width, height = dc.GetSizeTuple() |
403 |
|
mminx, mminy, mmaxx, mmaxy = self.mapregion |
404 |
|
|
405 |
|
# Page Frame |
406 |
|
dc.DrawRectangle(15,15,width-30, (mmaxy-mminy)+10) |
407 |
|
|
408 |
|
# Map Frame |
409 |
|
llx, lly, urx, ury = region |
410 |
|
dc.DrawRectangle(mminx + self.shiftx, mminy + self.shifty, urx, ury) |
411 |
|
|
412 |
|
# Legend Frame |
413 |
|
dc.DrawRectangle(mmaxx+10,mminy,(width-20) - (mmaxx+10), mmaxy-mminy) |
414 |
|
|
415 |
|
dc.DestroyClippingRegion() |
416 |
|
dc.SetClippingRegion(mmaxx+10,mminy, |
417 |
|
(width-20) - (mmaxx+10), mmaxy-mminy) |
418 |
|
|
419 |
|
def render_legend(self, map): |
420 |
|
"""Render the legend on the Map.""" |
421 |
|
|
422 |
|
previewer = ClassDataPreviewer() |
423 |
|
dc = self.dc |
424 |
|
dc.SetPen(wxBLACK_PEN) |
425 |
|
dc.SetBrush(wxTRANSPARENT_BRUSH) |
426 |
|
|
427 |
|
# Dimension stuff |
428 |
|
width, height = dc.GetSizeTuple() |
429 |
|
mminx, mminy, mmaxx, mmaxy = self.mapregion |
430 |
|
textwidth, textheight = dc.GetTextExtent("0") |
431 |
|
iconwidth = textheight |
432 |
|
iconheight = textheight |
433 |
|
stepy = textheight+3 |
434 |
|
dx = 10 |
435 |
|
posx = mmaxx + 10 + 5 # 10 pix distance mapframe/legend frame, |
436 |
|
# 5 pix inside legend frame |
437 |
|
posy = mminy + 5 # 5 pix inside legend frame |
438 |
|
|
439 |
|
# Render the legend |
440 |
|
dc.SetTextForeground(wxBLACK) |
441 |
|
if map.HasLayers(): |
442 |
|
for l in map.Layers(): |
443 |
|
if l.Visible(): |
444 |
|
# Render title |
445 |
|
dc.DrawText(l.Title(), posx, posy) |
446 |
|
posy+=stepy |
447 |
|
# Render classification |
448 |
|
clazz = l.GetClassification() |
449 |
|
shapeType = l.ShapeType() |
450 |
|
for g in clazz: |
451 |
|
if g.IsVisible(): |
452 |
|
previewer.Draw(dc, |
453 |
|
wxRect(posx+dx, posy, iconwidth, iconheight), |
454 |
|
g.GetProperties(), shapeType) |
455 |
|
dc.DrawText(g.GetDisplayText(), |
456 |
|
posx+2*dx+iconwidth, posy) |
457 |
|
posy+=stepy |
458 |
|
|
459 |
|
def render_scalebar(self, map): |
460 |
|
"""Render the scalebar.""" |
461 |
|
|
462 |
|
scalebar = ScaleBar(map) |
463 |
|
|
464 |
|
# Dimension stuff |
465 |
|
width, height = self.dc.GetSizeTuple() |
466 |
|
mminx, mminy, mmaxx, mmaxy = self.mapregion |
467 |
|
|
468 |
|
# Render the scalebar |
469 |
|
scalebar.DrawScaleBar(self.scale, self.dc, |
470 |
|
(mmaxx+10+5, mmaxy-25), |
471 |
|
((width-15-5) - (mmaxx+10+5),20) |
472 |
|
) |
473 |
|
# 10 pix between map and legend frame, 5 pix inside legend frame |
474 |
|
# 25 pix from the legend frame bottom line |
475 |
|
# Width: 15 pix from DC border, 5 pix inside frame, 10, 5 as above |
476 |
|
# Height: 20 |
477 |
|
|
478 |
|
class PrinterRenderer(ExportRenderer): |
479 |
|
|
480 |
|
# Printing as well as Export / Screen display only the visible layer. |
481 |
|
honor_visibility = 1 |
482 |
|
|