/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/UI/view.py
ViewVC logotype

Contents of /branches/WIP-pyshapelib-bramz/Thuban/UI/view.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1456 - (show annotations)
Fri Jul 18 14:56:13 2003 UTC (21 years, 7 months ago) by bh
Original Path: trunk/thuban/Thuban/UI/view.py
File MIME type: text/x-python
File size: 12313 byte(s)
* Thuban/UI/viewport.py: Remove unused imports

* Thuban/UI/view.py: Remove unused imports

1 # Copyright (c) 2001, 2002, 2003 by Intevation GmbH
2 # Authors:
3 # Bernhard Herzog <[email protected]>
4 # Frank Koormann <[email protected]>
5 #
6 # This program is free software under the GPL (>=v2)
7 # Read the file COPYING coming with Thuban for details.
8
9 """
10 Classes for display of a map and interaction with it
11 """
12
13 __version__ = "$Revision$"
14
15 from Thuban import _
16
17 import os.path
18
19 from wxPython.wx import wxWindow, \
20 wxPaintDC, wxColour, wxClientDC, wxINVERT, wxTRANSPARENT_BRUSH, wxFont,\
21 EVT_PAINT, EVT_LEFT_DOWN, EVT_LEFT_UP, EVT_MOTION, EVT_LEAVE_WINDOW, \
22 wxPlatform, wxBeginBusyCursor, wxEndBusyCursor, wxFileDialog, wxSAVE, \
23 wxOVERWRITE_PROMPT, wxID_OK
24
25 # Export related stuff
26 if wxPlatform == '__WXMSW__':
27 from wxPython.wx import wxMetaFileDC
28
29 from wxPython import wx
30
31 from Thuban.Model.messages import MAP_LAYERS_CHANGED, LAYER_CHANGED, \
32 LAYER_VISIBILITY_CHANGED
33
34 from renderer import ScreenRenderer, ExportRenderer, PrinterRenderer
35
36 import labeldialog
37
38 from viewport import ViewPort, PanTool, output_transform
39
40 class CanvasPanTool(PanTool):
41
42 """The Canvas Pan Tool"""
43
44 def MouseMove(self, event):
45 if self.dragging:
46 PanTool.MouseMove(self, event)
47 sx, sy = self.start
48 x, y = self.current
49 width, height = self.view.GetSizeTuple()
50
51 bitmapdc = wx.wxMemoryDC()
52 bitmapdc.SelectObject(self.view.bitmap)
53
54 dc = self.view.drag_dc
55 dc.Blit(0, 0, width, height, bitmapdc, sx - x, sy - y)
56
57 class MapPrintout(wx.wxPrintout):
58
59 """
60 wxPrintout class for printing Thuban maps
61 """
62
63 def __init__(self, canvas, map, region, selected_layer, selected_shapes):
64 wx.wxPrintout.__init__(self)
65 self.canvas = canvas
66 self.map = map
67 self.region = region
68 self.selected_layer = selected_layer
69 self.selected_shapes = selected_shapes
70
71 def GetPageInfo(self):
72 return (1, 1, 1, 1)
73
74 def HasPage(self, pagenum):
75 return pagenum == 1
76
77 def OnPrintPage(self, pagenum):
78 if pagenum == 1:
79 self.draw_on_dc(self.GetDC())
80
81 def draw_on_dc(self, dc):
82 width, height = self.GetPageSizePixels()
83 scale, offset, mapregion = output_transform(self.canvas.scale,
84 self.canvas.offset,
85 self.canvas.GetSizeTuple(),
86 self.GetPageSizePixels())
87 resx, resy = self.GetPPIPrinter()
88 renderer = PrinterRenderer(dc, scale, offset, resolution = resy)
89 x, y, width, height = self.region
90 canvas_scale = self.canvas.scale
91 renderer.RenderMap(self.map,
92 (0,0,
93 (width/canvas_scale)*scale,
94 (height/canvas_scale)*scale),
95 mapregion,
96 self.selected_layer, self.selected_shapes)
97 return True
98
99 class MapCanvas(wxWindow, ViewPort):
100
101 """A widget that displays a map and offers some interaction"""
102
103 def __init__(self, parent, winid):
104 wxWindow.__init__(self, parent, winid)
105 ViewPort.__init__(self)
106
107 self.SetBackgroundColour(wxColour(255, 255, 255))
108
109 # the bitmap serving as backing store
110 self.bitmap = None
111
112 self.backgroundColor = wx.wxWHITE_BRUSH
113
114 # subscribe the WX events we're interested in
115 EVT_PAINT(self, self.OnPaint)
116 EVT_LEFT_DOWN(self, self.OnLeftDown)
117 EVT_LEFT_UP(self, self.OnLeftUp)
118 EVT_MOTION(self, self.OnMotion)
119 EVT_LEAVE_WINDOW(self, self.OnLeaveWindow)
120 wx.EVT_SIZE(self, self.OnSize)
121 wx.EVT_IDLE(self, self.OnIdle)
122
123 def __del__(self):
124 wxWindow.__del__(self)
125 ViewPort.__del__(self)
126
127 def PanTool(self):
128 """Start the canvas pan tool"""
129 self.SelectTool(CanvasPanTool(self))
130
131 def SetMap(self, map):
132 redraw_channels = (MAP_LAYERS_CHANGED, LAYER_CHANGED,
133 LAYER_VISIBILITY_CHANGED)
134 if self.Map() is not None:
135 for channel in redraw_channels:
136 self.Map().Unsubscribe(channel, self.full_redraw)
137
138 ViewPort.SetMap(self, map)
139
140 if self.Map() is not None:
141 for channel in redraw_channels:
142 self.Map().Subscribe(channel, self.full_redraw)
143
144 # force a redraw. If map is not empty, it's already been called
145 # by FitMapToWindow but if map is empty it hasn't been called
146 # yet so we have to explicitly call it.
147 self.full_redraw()
148
149 def OnPaint(self, event):
150 dc = wxPaintDC(self)
151
152 if self.Map() is not None and self.Map().HasLayers():
153 if self.bitmap in (None, -1):
154 # set the flag that we should redraw the
155 # bitmap in idle time
156 self.bitmap = -1
157 else:
158 # blit the bitmap to the screen
159 dc.BeginDrawing()
160 dc.DrawBitmap(self.bitmap, 0, 0)
161 dc.EndDrawing()
162 else:
163 # If we've got no map or if the map is empty, simply clear
164 # the screen.
165
166 # XXX it's probably possible to get rid of this. The
167 # background color of the window is already white and the
168 # only thing we may have to do is to call self.Refresh()
169 # with a true argument in the right places.
170 dc.BeginDrawing()
171 dc.SetBackground(self.backgroundColor)
172 dc.Clear()
173 dc.EndDrawing()
174
175 def OnIdle(self, event):
176 # render the screen if necessary
177
178 if self.bitmap != -1:
179 return
180
181 wxBeginBusyCursor()
182 try:
183 width, height = self.GetSizeTuple()
184
185 bitmap = wx.wxEmptyBitmap(width, height)
186 dc = wx.wxMemoryDC()
187 dc.SelectObject(bitmap)
188 dc.BeginDrawing()
189
190 dc.SetBackground(self.backgroundColor)
191 dc.Clear()
192
193 selected_layer = self.selection.SelectedLayer()
194 selected_shapes = self.selection.SelectedShapes()
195
196 # draw the map into the bitmap
197 renderer = ScreenRenderer(dc, self.scale, self.offset)
198
199 # Pass the entire bitmap as update region to the renderer.
200 # We're redrawing the whole bitmap, after all.
201 renderer.RenderMap(self.Map(), (0, 0, width, height),
202 selected_layer, selected_shapes)
203
204 dc.EndDrawing()
205 dc.SelectObject(wx.wxNullBitmap)
206
207 self.bitmap = bitmap
208 finally:
209 wxEndBusyCursor()
210 pass
211
212 # This causes a paint event that then draws the bitmap
213 self.redraw()
214
215 def Export(self):
216
217 if hasattr(self, "export_path"):
218 export_path = self.export_path
219 else:
220 export_path="."
221 dlg = wxFileDialog(self, _("Export Map"), export_path, "",
222 "Enhanced Metafile (*.wmf)|*.wmf",
223 wxSAVE|wxOVERWRITE_PROMPT)
224 if dlg.ShowModal() == wxID_OK:
225 self.export_path = os.path.dirname(dlg.GetPath())
226 dc = wxMetaFileDC(dlg.GetPath())
227
228 scale, offset, mapregion = output_transform(self.scale,
229 self.offset,
230 self.GetSizeTuple(),
231 dc.GetSizeTuple())
232
233 selected_layer = self.selection.SelectedLayer()
234 selected_shapes = self.selection.SelectedShapes()
235
236 renderer = ExportRenderer(dc, scale, offset)
237
238 # Pass the entire bitmap as update region to the renderer.
239 # We're redrawing the whole bitmap, after all.
240 width, height = self.GetSizeTuple()
241 renderer.RenderMap(self.Map(),
242 (0,0,
243 (width/self.scale)*scale,
244 (height/self.scale)*scale),
245 mapregion,
246 selected_layer, selected_shapes)
247 dc.EndDrawing()
248 dc.Close()
249 dlg.Destroy()
250
251 def Print(self):
252 printer = wx.wxPrinter()
253 width, height = self.GetSizeTuple()
254 selected_layer = self.selection.SelectedLayer()
255 selected_shapes = self.selection.SelectedShapes()
256
257 printout = MapPrintout(self, self.Map(), (0, 0, width, height),
258 selected_layer, selected_shapes)
259 printer.Print(self, printout, True)
260 printout.Destroy()
261
262 def redraw(self, *args):
263 self.Refresh(False)
264
265 def full_redraw(self, *args):
266 self.bitmap = None
267 self.redraw()
268
269 def map_projection_changed(self, map, old_proj):
270 ViewPort.map_projection_changed(self, map, old_proj)
271 self.full_redraw()
272
273 def layer_projection_changed(self, *args):
274 ViewPort.layer_projection_changed(self, args)
275 self.full_redraw()
276
277 def set_view_transform(self, scale, offset):
278 ViewPort.set_view_transform(self, scale, offset)
279 self.full_redraw()
280
281 def GetPortSizeTuple(self):
282 return self.GetSizeTuple()
283
284 def OnLeftDown(self, event):
285 self.MouseLeftDown(event)
286 if self.tool is not None:
287 self.drag_dc = wxClientDC(self)
288 self.drag_dc.SetLogicalFunction(wxINVERT)
289 self.drag_dc.SetBrush(wxTRANSPARENT_BRUSH)
290 self.tool.Show(self.drag_dc)
291 self.dragging = 1
292
293 def OnLeftUp(self, event):
294 self.MouseLeftUp(event)
295 if self.dragging:
296 self.ReleaseMouse()
297 try:
298 self.tool.Hide(self.drag_dc)
299 finally:
300 self.drag_dc = None
301 self.dragging = 0
302
303 def OnMotion(self, event):
304 if self.dragging:
305 self.tool.Hide(self.drag_dc)
306
307 self.MouseMove(event)
308
309 if self.dragging:
310 self.tool.Show(self.drag_dc)
311
312 def OnLeaveWindow(self, event):
313 self.set_current_position(None)
314
315 def OnSize(self, event):
316 # the window's size has changed. We have to get a new bitmap. If
317 # we want to be clever we could try to get by without throwing
318 # everything away. E.g. when the window gets smaller, we could
319 # either keep the bitmap or create the new one from the old one.
320 # Even when the window becomes larger some parts of the bitmap
321 # could be reused.
322 self.full_redraw()
323
324 def shape_selected(self, layer, shape):
325 """Receiver for the SHAPES_SELECTED messages. Redraw the map."""
326 # The selection object takes care that it only issues
327 # SHAPES_SELECTED messages when the set of selected shapes has
328 # actually changed, so we can do a full redraw unconditionally.
329 # FIXME: We should perhaps try to limit the redraw to the are
330 # actually covered by the shapes before and after the selection
331 # change.
332 ViewPort.shape_selected(self, layer, shape)
333 self.full_redraw()
334
335 def GetTextExtent(self, text):
336 dc = wxClientDC(self)
337 font = wxFont(10, wx.wxSWISS, wx.wxNORMAL, wx.wxNORMAL)
338 dc.SetFont(font)
339 return dc.GetTextExtent(text)
340
341 def LabelShapeAt(self, x, y, text=None):
342 """Add or remove a label at window position x, y.
343
344 If there's a label at the given position, remove it. Otherwise
345 determine the shape at the position, run the label dialog and
346 unless the user cancels the dialog, add a label.
347 """
348 label_layer = self.map.LabelLayer()
349 layer, shape_index = self.find_shape_at(x, y, select_labels = 1)
350 if layer is None and shape_index is not None:
351 ViewPort.LabelShapeAt(self, x, y)
352 elif layer is not None:
353 text = labeldialog.run_label_dialog(self,
354 layer.ShapeStore().Table(),
355 shape_index)
356 ViewPort.LabelShapeAt(self, x, y, text)

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26