~ubuntu-branches/ubuntu/vivid/grass/vivid-proposed

« back to all changes in this revision

Viewing changes to gui/wxpython/gui_core/mapdisp.py

  • Committer: Package Import Robot
  • Author(s): Bas Couwenberg
  • Date: 2015-02-20 23:12:08 UTC
  • mfrom: (8.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20150220231208-1u6qvqm84v430b10
Tags: 7.0.0-1~exp1
* New upstream release.
* Update python-ctypes-ternary.patch to use if/else instead of and/or.
* Drop check4dev patch, rely on upstream check.
* Add build dependency on libpq-dev to grass-dev for libpq-fe.h.
* Drop patches applied upstream, refresh remaining patches.
* Update symlinks for images switched from jpg to png.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
"""!
 
1
"""
2
2
@package gui_core.mapdisp
3
3
 
4
4
@brief Base classes for Map display window
5
5
 
6
6
Classes:
7
7
 - mapdisp::MapFrameBase
 
8
 - mapdisp::SingleMapFrame
 
9
 - mapdisp::DoubleMapFrame
8
10
 
9
 
(C) 2009-2011 by the GRASS Development Team
 
11
(C) 2009-2014 by the GRASS Development Team
10
12
 
11
13
This program is free software under the GNU General Public License
12
14
(>=v2). Read the file COPYING that comes with GRASS for details.
13
15
 
14
16
@author Martin Landa <landa.martin gmail.com>
15
17
@author Michael Barton <michael.barton@asu.edu>
 
18
@author Vaclav Petras <wenzeslaus gmail.com>
 
19
@author Anna Kratochvilova <kratochanna gmail.com>
16
20
"""
17
21
 
18
22
import os
19
23
import sys
20
24
 
21
25
import wx
 
26
import wx.aui
22
27
 
23
 
from core       import globalvar
24
 
from core.debug import Debug
 
28
from core        import globalvar
 
29
from core.debug  import Debug
 
30
from core.utils import _
 
31
from gui_core.toolbars import ToolSwitcher
25
32
 
26
33
from grass.script import core as grass
27
34
 
 
35
 
28
36
class MapFrameBase(wx.Frame):
29
 
    """!Base class for map display window
30
 
    
31
 
    Derived class must use statusbarManager or override
32
 
    GetProperty, SetProperty and HasProperty methods.
 
37
    """Base class for map display window
 
38
    
 
39
    Derived class must use (create and initialize) \c statusbarManager
 
40
    or override
 
41
    GetProperty(), SetProperty() and HasProperty() methods.
 
42
    
 
43
    Several methods has to be overriden or
 
44
    \c NotImplementedError("MethodName") will be raised.
 
45
    
33
46
    If derived class enables and disables auto-rendering,
34
47
    it should override IsAutoRendered method.
 
48
 
 
49
    It is expected that derived class will call _setUpMapWindow().
 
50
 
 
51
    Derived class can has one or more map windows (and map renderes)
 
52
    but implementation of MapFrameBase expects that one window and
 
53
    one map will be current.
 
54
    Current instances of map window and map renderer should be returned
 
55
    by methods GetWindow() and GetMap() respectively.
 
56
    
 
57
    AUI manager is stored in \c self._mgr.
35
58
    """
36
59
    def __init__(self, parent = None, id = wx.ID_ANY, title = None,
37
 
                 style = wx.DEFAULT_FRAME_STYLE, toolbars = None,
38
 
                 Map = None, auimgr = None, name = None, **kwargs):
39
 
        """!
40
 
        @param toolbars array of activated toolbars, e.g. ['map', 'digit']
41
 
        @param Map instance of render.Map
42
 
        @param auimgs AUI manager
43
 
        @param name frame name
44
 
        @param kwargs wx.Frame attributes
 
60
                 style = wx.DEFAULT_FRAME_STYLE,
 
61
                 auimgr = None, name = None, **kwargs):
45
62
        """
46
 
        
47
63
 
48
 
        self.Map        = Map       # instance of render.Map
 
64
        .. warning::
 
65
            Use \a auimgr parameter only if you know what you are doing.
 
66
        
 
67
        :param parent: gui parent
 
68
        :param id: wx id
 
69
        :param title: window title
 
70
        :param style: \c wx.Frame style
 
71
        :param toolbars: array of activated toolbars, e.g. ['map', 'digit']
 
72
        :param auimgr: AUI manager (if \c None, wx.aui.AuiManager is used)
 
73
        :param name: frame name
 
74
        :param kwargs: arguments passed to \c wx.Frame
 
75
        """
 
76
        
49
77
        self.parent     = parent
50
78
        
51
79
        wx.Frame.__init__(self, parent, id, title, style = style, name = name, **kwargs)
52
 
        
53
 
        # available cursors
54
 
        self.cursors = {
55
 
            # default: cross
56
 
            # "default" : wx.StockCursor(wx.CURSOR_DEFAULT),
57
 
            "default" : wx.StockCursor(wx.CURSOR_ARROW),
58
 
            "cross"   : wx.StockCursor(wx.CURSOR_CROSS),
59
 
            "hand"    : wx.StockCursor(wx.CURSOR_HAND),
60
 
            "pencil"  : wx.StockCursor(wx.CURSOR_PENCIL),
61
 
            "sizenwse": wx.StockCursor(wx.CURSOR_SIZENWSE)
62
 
            }
63
80
                
64
81
        #
65
82
        # set the size & system icon
67
84
        self.SetClientSize(self.GetSize())
68
85
        self.iconsize = (16, 16)
69
86
 
70
 
        self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass_map.ico'), wx.BITMAP_TYPE_ICO))
 
87
        self.SetIcon(wx.Icon(os.path.join(globalvar.ICONDIR, 'grass_map.ico'), wx.BITMAP_TYPE_ICO))
71
88
        
72
89
        # toolbars
73
90
        self.toolbars = {}
75
92
        #
76
93
        # Fancy gui
77
94
        #
78
 
        self._mgr = wx.aui.AuiManager(self)
 
95
        if auimgr == None:
 
96
            self._mgr = wx.aui.AuiManager(self)
 
97
        else:
 
98
            self._mgr = auimgr
79
99
        
80
 
    def _initMap(self, map):
81
 
        """!Initialize map display, set dimensions and map region
 
100
        # handles switching between tools in different toolbars
 
101
        self._toolSwitcher = ToolSwitcher()
 
102
        self._toolSwitcher.toggleToolChanged.connect(self._onToggleTool)
 
103
 
 
104
        # set accelerator table for fullscreen
 
105
        fullScreenId = wx.NewId()
 
106
        self.Bind(wx.EVT_MENU, self.OnFullScreen, id=fullScreenId)
 
107
        accelTable = wx.AcceleratorTable([(wx.ACCEL_NORMAL, wx.WXK_F11, fullScreenId)])
 
108
        self.SetAcceleratorTable(accelTable)
 
109
 
 
110
    def _initMap(self, Map):
 
111
        """Initialize map display, set dimensions and map region
82
112
        """
83
 
        if not grass.find_program('g.region', ['--help']):
 
113
        if not grass.find_program('g.region', '--help'):
84
114
            sys.exit(_("GRASS module '%s' not found. Unable to start map "
85
115
                       "display window.") % 'g.region')
86
116
        
87
 
        self.width, self.height = self.GetClientSize()
88
 
        
89
117
        Debug.msg(2, "MapFrame._initMap():")
90
 
        map.ChangeMapSize(self.GetClientSize())
91
 
        map.region = map.GetRegion() # g.region -upgc
 
118
        Map.ChangeMapSize(self.GetClientSize())
 
119
        Map.region = Map.GetRegion() # g.region -upgc
92
120
        # self.Map.SetRegion() # adjust region to match display window
 
121
 
 
122
    def _onToggleTool(self):
 
123
        self.GetWindow().UnregisterAllHandlers()
 
124
 
 
125
    def OnSize(self, event):
 
126
        """Adjust statusbar on changing size"""
 
127
        # reposition checkbox in statusbar
 
128
        self.StatusbarReposition()
93
129
        
 
130
        # update statusbar
 
131
        self.StatusbarUpdate()
 
132
 
 
133
    def OnFullScreen(self, event):
 
134
        """!Switch fullscreen mode, hides also toolbars"""
 
135
        for toolbar in self.toolbars.keys():
 
136
            self._mgr.GetPane(self.toolbars[toolbar]).Show(self.IsFullScreen())
 
137
        self._mgr.Update()
 
138
        self.ShowFullScreen(not self.IsFullScreen())
 
139
        event.Skip()
 
140
 
 
141
    def GetToolSwitcher(self):
 
142
        return self._toolSwitcher
 
143
 
94
144
    def SetProperty(self, name, value):
95
 
        """!Sets property"""
 
145
        """Sets property"""
96
146
        self.statusbarManager.SetProperty(name, value)
97
147
        
98
148
    def GetProperty(self, name):
99
 
        """!Returns property"""
 
149
        """Returns property"""
100
150
        return self.statusbarManager.GetProperty(name)
101
151
        
102
152
    def HasProperty(self, name):
103
 
        """!Checks whether object has property"""
 
153
        """Checks whether object has property"""
104
154
        return self.statusbarManager.HasProperty(name)
105
155
    
106
156
    def GetPPM(self):
107
 
        """! Get pixel per meter
108
 
        
109
 
        @todo now computed every time, is it necessary?
110
 
        @todo enable user to specify ppm (and store it in UserSettings)
 
157
        """Get pixel per meter
 
158
        
 
159
        .. todo::
 
160
            now computed every time, is it necessary?
 
161
        
 
162
        .. todo::
 
163
            enable user to specify ppm (and store it in UserSettings)
111
164
        """
112
165
        # TODO: need to be fixed...
113
166
        ### screen X region problem
134
187
        return ppm
135
188
    
136
189
    def SetMapScale(self, value, map = None):
137
 
        """! Set current map scale
 
190
        """Set current map scale
138
191
        
139
 
        @param value scale value (n if scale is 1:n)
140
 
        @param map Map instance (if none self.Map is used)
 
192
        :param value: scale value (n if scale is 1:n)
 
193
        :param map: Map instance (if none self.Map is used)
141
194
        """
142
195
        if not map:
143
196
            map = self.Map
155
208
                                   region['e'], region['w'])
156
209
    
157
210
    def GetMapScale(self, map = None):
158
 
        """! Get current map scale
 
211
        """Get current map scale
159
212
        
160
 
        @param map Map instance (if none self.Map is used)
 
213
        :param map: Map instance (if none self.Map is used)
161
214
        """
162
215
        if not map:
163
 
            map = self.Map
 
216
            map = self.GetMap()
164
217
        
165
218
        region = map.region
166
219
        ppm = self.GetPPM()
181
234
        return scale
182
235
        
183
236
    def GetProgressBar(self):
184
 
        """!Returns progress bar
 
237
        """Returns progress bar
185
238
        
186
239
        Progress bar can be used by other classes.
187
240
        """
188
241
        return self.statusbarManager.GetProgressBar()
189
242
        
190
243
    def GetMap(self):
191
 
        """!Returns current Map instance
192
 
        """
193
 
        return self.Map
 
244
        """Returns current map (renderer) instance"""
 
245
        raise NotImplementedError("GetMap")
194
246
 
195
247
    def GetWindow(self):
196
 
        """!Get map window"""
197
 
        return self.MapWindow
 
248
        """Returns current map window"""
 
249
        raise NotImplementedError("GetWindow")
 
250
 
 
251
    def GetWindows(self):
 
252
        """Returns list of map windows"""
 
253
        raise NotImplementedError("GetWindows")
198
254
        
199
255
    def GetMapToolbar(self):
200
 
       """!Returns toolbar with zooming tools"""
201
 
       raise NotImplementedError()
 
256
        """Returns toolbar with zooming tools"""
 
257
        raise NotImplementedError("GetMapToolbar")
202
258
       
203
259
    def GetToolbar(self, name):
204
 
        """!Returns toolbar if exists else None.
 
260
        """Returns toolbar if exists else None.
205
261
        
206
262
        Toolbars dictionary contains currently used toolbars only.
207
263
        """
211
267
        return None
212
268
       
213
269
    def StatusbarUpdate(self):
214
 
        """!Update statusbar content"""
 
270
        """Update statusbar content"""
 
271
        Debug.msg(5, "MapFrameBase.StatusbarUpdate()")
215
272
        self.statusbarManager.Update()
216
273
        
217
274
    def IsAutoRendered(self):
218
 
        """!Check if auto-rendering is enabled"""
219
 
        return self.GetProperty('render')
 
275
        """Check if auto-rendering is enabled"""
 
276
        # TODO: this is now not the right place to access this attribute
 
277
        # TODO: add mapWindowProperties to init parameters
 
278
        # and pass the right object in the init of derived class?
 
279
        # or do not use this method at all, let mapwindow decide
 
280
        return self.mapWindowProperties.autoRender
220
281
        
221
282
    def CoordinatesChanged(self):
222
 
        """!Shows current coordinates on statusbar.
223
 
        
224
 
        Used in BufferedWindow to report change of map coordinates (under mouse cursor).
 
283
        """Shows current coordinates on statusbar.
225
284
        """
226
 
        self.statusbarManager.ShowItem('coordinates')
 
285
        # assuming that the first mode is coordinates
 
286
        # probably shold not be here but good solution is not available now
 
287
        if self.statusbarManager.GetMode() == 0:
 
288
            self.statusbarManager.ShowItem('coordinates')
227
289
        
228
290
    def StatusbarReposition(self):
229
 
        """!Reposition items in statusbar"""
 
291
        """Reposition items in statusbar"""
230
292
        self.statusbarManager.Reposition()
231
293
        
232
294
    def StatusbarEnableLongHelp(self, enable = True):
233
 
        """!Enable/disable toolbars long help"""
 
295
        """Enable/disable toolbars long help"""
234
296
        for toolbar in self.toolbars.itervalues():
235
297
            toolbar.EnableLongHelp(enable)
236
298
        
237
299
    def IsStandalone(self):
238
 
        """!Check if Map display is standalone"""
 
300
        """Check if map frame is standalone"""
239
301
        raise NotImplementedError("IsStandalone")
240
302
   
241
303
    def OnRender(self, event):
242
 
        """!Re-render map composition (each map layer)
 
304
        """Re-render map composition (each map layer)
243
305
        """
244
306
        raise NotImplementedError("OnRender")
245
307
        
246
308
    def OnDraw(self, event):
247
 
        """!Re-display current map composition
 
309
        """Re-display current map composition
248
310
        """
249
311
        self.MapWindow.UpdateMap(render = False)
250
312
        
251
313
    def OnErase(self, event):
252
 
        """!Erase the canvas
 
314
        """Erase the canvas
253
315
        """
254
316
        self.MapWindow.EraseMap()
255
317
        
256
318
    def OnZoomIn(self, event):
257
 
        """!Zoom in the map.
258
 
        Set mouse cursor, zoombox attributes, and zoom direction
259
 
        """
260
 
        toolbar = self.GetMapToolbar()
261
 
        self._switchTool(toolbar, event)
262
 
        
263
 
        win = self.GetWindow()
264
 
        self._prepareZoom(mapWindow = win, zoomType = 1)
 
319
        """Zoom in the map."""
 
320
        self.MapWindow.SetModeZoomIn()
265
321
        
266
322
    def OnZoomOut(self, event):
267
 
        """!Zoom out the map.
268
 
        Set mouse cursor, zoombox attributes, and zoom direction
269
 
        """
270
 
        toolbar = self.GetMapToolbar()
271
 
        self._switchTool(toolbar, event)
272
 
        
273
 
        win = self.GetWindow()
274
 
        self._prepareZoom(mapWindow = win, zoomType = -1)
275
 
        
276
 
    def _prepareZoom(self, mapWindow, zoomType):
277
 
        """!Prepares MapWindow for zoom, toggles toolbar
278
 
        
279
 
        @param mapWindow MapWindow to prepare
280
 
        @param zoomType 1 for zoom in, -1 for zoom out
281
 
        """
282
 
        mapWindow.mouse['use'] = "zoom"
283
 
        mapWindow.mouse['box'] = "box"
284
 
        mapWindow.zoomtype = zoomType
285
 
        mapWindow.pen = wx.Pen(colour = 'Red', width = 2, style = wx.SHORT_DASH)
286
 
        
287
 
        # change the cursor
288
 
        mapWindow.SetCursor(self.cursors["cross"])
289
 
    
290
 
    def _switchTool(self, toolbar, event):
291
 
        """!Helper function to switch tools"""
292
 
        if toolbar:
293
 
            toolbar.OnTool(event)
294
 
            toolbar.action['desc'] = ''
295
 
            
 
323
        """Zoom out the map."""
 
324
        self.MapWindow.SetModeZoomOut()
 
325
 
 
326
    def _setUpMapWindow(self, mapWindow):
 
327
        """Binds map windows' zoom history signals to map toolbar."""
 
328
        # enable or disable zoom history tool
 
329
        mapWindow.zoomHistoryAvailable.connect(
 
330
            lambda:
 
331
            self.GetMapToolbar().Enable('zoomBack', enable=True))
 
332
        mapWindow.zoomHistoryUnavailable.connect(
 
333
            lambda:
 
334
            self.GetMapToolbar().Enable('zoomBack', enable=False))
 
335
        mapWindow.mouseMoving.connect(self.CoordinatesChanged)
 
336
 
296
337
    def OnPointer(self, event):
297
 
        """!Sets mouse mode to pointer."""
298
 
        self.MapWindow.mouse['use'] = 'pointer'
 
338
        """Sets mouse mode to pointer."""
 
339
        self.MapWindow.SetModePointer()
299
340
 
300
341
    def OnPan(self, event):
301
 
        """!Panning, set mouse to drag
302
 
        """
303
 
        toolbar = self.GetMapToolbar()
304
 
        self._switchTool(toolbar, event)
305
 
        
306
 
        win = self.GetWindow()
307
 
        self._preparePan(mapWindow = win)
308
 
    
309
 
    def _preparePan(self, mapWindow):
310
 
        """!Prepares MapWindow for pan, toggles toolbar
311
 
        
312
 
        @param mapWindow MapWindow to prepare
313
 
        """
314
 
        mapWindow.mouse['use'] = "pan"
315
 
        mapWindow.mouse['box'] = "pan"
316
 
        mapWindow.zoomtype = 0
317
 
        
318
 
        # change the cursor
319
 
        mapWindow.SetCursor(self.cursors["hand"])
320
 
        
 
342
        """Panning, set mouse to drag
 
343
        """
 
344
        self.MapWindow.SetModePan()
 
345
 
321
346
    def OnZoomBack(self, event):
322
 
        """!Zoom last (previously stored position)
 
347
        """Zoom last (previously stored position)
323
348
        """
324
349
        self.MapWindow.ZoomBack()
325
350
        
326
351
    def OnZoomToMap(self, event):
327
 
        """!
 
352
        """
328
353
        Set display extents to match selected raster (including NULLs)
329
354
        or vector map.
330
355
        """
331
356
        self.MapWindow.ZoomToMap(layers = self.Map.GetListOfLayers())
332
357
    
333
358
    def OnZoomToWind(self, event):
334
 
        """!Set display geometry to match computational region
 
359
        """Set display geometry to match computational region
335
360
        settings (set with g.region)
336
361
        """
337
362
        self.MapWindow.ZoomToWind()
338
363
        
339
364
    def OnZoomToDefault(self, event):
340
 
        """!Set display geometry to match default region settings
 
365
        """Set display geometry to match default region settings
341
366
        """
342
367
        self.MapWindow.ZoomToDefault()
 
368
 
 
369
 
 
370
class SingleMapFrame(MapFrameBase):
 
371
    """Frame with one map window.
 
372
    
 
373
    It is base class for frames which needs only one map.
 
374
    
 
375
    Derived class should have \c self.MapWindow or
 
376
    it has to override GetWindow() methods.
 
377
    
 
378
    @note To access maps use getters only
 
379
    (when using class or when writing class itself).
 
380
    """
 
381
    def __init__(self, parent = None, giface = None, id = wx.ID_ANY, title = None,
 
382
                 style = wx.DEFAULT_FRAME_STYLE,
 
383
                 Map = None,
 
384
                 auimgr = None, name = None, **kwargs):
 
385
        """
 
386
        
 
387
        :param parent: gui parent
 
388
        :param id: wx id
 
389
        :param title: window title
 
390
        :param style: \c wx.Frame style
 
391
        :param map: instance of render.Map
 
392
        :param name: frame name
 
393
        :param kwargs: arguments passed to MapFrameBase
 
394
        """
 
395
 
 
396
        MapFrameBase.__init__(self, parent = parent, id = id, title = title,
 
397
                              style = style,
 
398
                              auimgr = auimgr, name = name, **kwargs)
 
399
 
 
400
        self.Map = Map       # instance of render.Map
 
401
 
 
402
        #
 
403
        # initialize region values
 
404
        #
 
405
        self._initMap(Map = self.Map)
 
406
        
 
407
    def GetMap(self):
 
408
        """Returns map (renderer) instance"""
 
409
        return self.Map
 
410
 
 
411
    def GetWindow(self):
 
412
        """Returns map window"""
 
413
        return self.MapWindow
 
414
        
 
415
    def GetWindows(self):
 
416
        """Returns list of map windows"""
 
417
        return [self.MapWindow]
 
418
 
 
419
    def OnRender(self, event):
 
420
        """Re-render map composition (each map layer)
 
421
        """
 
422
        self.GetWindow().UpdateMap(render = True, renderVector = True)
 
423
        
 
424
        # update statusbar
 
425
        self.StatusbarUpdate()
 
426
        
 
427
 
 
428
class DoubleMapFrame(MapFrameBase):
 
429
    """Frame with two map windows.
 
430
    
 
431
    It is base class for frames which needs two maps.
 
432
    There is no primary and secondary map. Both maps are equal.
 
433
    However, one map is current.
 
434
    
 
435
    It is expected that derived class will call _bindWindowsActivation()
 
436
    when both map windows will be initialized.
 
437
    
 
438
    Drived class should have method GetMapToolbar() returns toolbar
 
439
    which has methods SetActiveMap() and Enable().
 
440
    
 
441
    @note To access maps use getters only
 
442
    (when using class or when writing class itself).
 
443
    
 
444
    .. todo:
 
445
        Use it in GCP manager (probably changes to both DoubleMapFrame
 
446
        and GCP MapFrame will be neccessary).
 
447
    """
 
448
    def __init__(self, parent = None, id = wx.ID_ANY, title = None,
 
449
                 style = wx.DEFAULT_FRAME_STYLE,
 
450
                 firstMap = None, secondMap = None,
 
451
                 auimgr = None, name = None, **kwargs):
 
452
        """
 
453
        
 
454
        \a firstMap is set as active (by assign it to \c self.Map).
 
455
        Derived class should assging to \c self.MapWindow to make one
 
456
        map window current by dafault.
 
457
        
 
458
        :param parent: gui parent
 
459
        :param id: wx id
 
460
        :param title: window title
 
461
        :param style: \c wx.Frame style
 
462
        :param name: frame name
 
463
        :param kwargs: arguments passed to MapFrameBase
 
464
        """
 
465
        
 
466
        MapFrameBase.__init__(self, parent = parent, id = id, title = title,
 
467
                              style = style,
 
468
                              auimgr = auimgr, name = name, **kwargs)
 
469
        
 
470
        self.firstMap = firstMap
 
471
        self.secondMap = secondMap
 
472
        self.Map = firstMap
 
473
 
 
474
        #
 
475
        # initialize region values
 
476
        #
 
477
        self._initMap(Map = self.firstMap)
 
478
        self._initMap(Map = self.secondMap)
 
479
        self._bindRegions = False
 
480
    
 
481
    def _bindWindowsActivation(self):
 
482
        self.GetFirstWindow().Bind(wx.EVT_ENTER_WINDOW, self.ActivateFirstMap)
 
483
        self.GetSecondWindow().Bind(wx.EVT_ENTER_WINDOW, self.ActivateSecondMap)
 
484
    
 
485
    def _onToggleTool(self):
 
486
        self.GetFirstWindow().UnregisterAllHandlers()
 
487
        self.GetSecondWindow().UnregisterAllHandlers()
 
488
 
 
489
    def GetFirstMap(self):
 
490
        """Returns first Map instance
 
491
        """
 
492
        return self.firstMap
 
493
        
 
494
    def GetSecondMap(self):
 
495
        """Returns second Map instance
 
496
        """
 
497
        return self.secondMap
 
498
        
 
499
    def GetFirstWindow(self):
 
500
        """Get first map window"""
 
501
        return self.firstMapWindow
 
502
    
 
503
    def GetSecondWindow(self):
 
504
        """Get second map window"""
 
505
        return self.secondMapWindow
 
506
    
 
507
    def GetMap(self):
 
508
        """Returns current map (renderer) instance
 
509
        
 
510
        @note Use this method to access current map renderer.
 
511
        (It is not guarented that current map will be stored in
 
512
        \c self.Map in future versions.)
 
513
        """
 
514
        return self.Map
 
515
    
 
516
    def GetWindow(self):
 
517
        """Returns current map window
 
518
        
 
519
        :func:`GetMap()`
 
520
        """
 
521
        return self.MapWindow
 
522
    
 
523
    def GetWindows(self):
 
524
        """Return list of all windows"""
 
525
        return [self.firstMapWindow, self.secondMapWindow]
 
526
    
 
527
    def ActivateFirstMap(self, event = None):
 
528
        """Make first Map and MapWindow active and (un)bind regions of the two Maps."""
 
529
        if self.MapWindow == self.firstMapWindow:
 
530
            return
 
531
 
 
532
        self.Map = self.firstMap
 
533
        self.MapWindow = self.firstMapWindow
 
534
        self.GetMapToolbar().SetActiveMap(0)
 
535
 
 
536
        # bind/unbind regions
 
537
        if self._bindRegions:
 
538
            self.firstMapWindow.zoomChanged.connect(self.OnZoomChangedFirstMap)
 
539
            self.secondMapWindow.zoomChanged.disconnect(self.OnZoomChangedSecondMap)
 
540
 
 
541
    def ActivateSecondMap(self, event = None):
 
542
        """Make second Map and MapWindow active and (un)bind regions of the two Maps."""
 
543
        if self.MapWindow == self.secondMapWindow:
 
544
            return        
 
545
 
 
546
        self.Map = self.secondMap
 
547
        self.MapWindow = self.secondMapWindow
 
548
        self.GetMapToolbar().SetActiveMap(1)
 
549
 
 
550
        if self._bindRegions:
 
551
            self.secondMapWindow.zoomChanged.connect(self.OnZoomChangedSecondMap)
 
552
            self.firstMapWindow.zoomChanged.disconnect(self.OnZoomChangedFirstMap)
 
553
 
 
554
    def SetBindRegions(self, on):
 
555
        """Set or unset binding display regions."""
 
556
        self._bindRegions = on
 
557
 
 
558
        if on:
 
559
            if self.MapWindow == self.firstMapWindow:
 
560
                self.firstMapWindow.zoomChanged.connect(self.OnZoomChangedFirstMap)
 
561
            else:
 
562
                self.secondMapWindow.zoomChanged.connect(self.OnZoomChangedSecondMap)
 
563
        else:
 
564
            if self.MapWindow == self.firstMapWindow:
 
565
                self.firstMapWindow.zoomChanged.disconnect(self.OnZoomChangedFirstMap)
 
566
            else:
 
567
                self.secondMapWindow.zoomChanged.disconnect(self.OnZoomChangedSecondMap)
 
568
 
 
569
    def OnZoomChangedFirstMap(self):
 
570
        """Display region of the first window (Map) changed.
 
571
 
 
572
        Synchronize the region of the second map and re-render it.
 
573
        This is the default implementation which can be overridden.
 
574
        """
 
575
        region = self.GetFirstMap().GetCurrentRegion()
 
576
        self.GetSecondMap().region.update(region)
 
577
        self.Render(mapToRender = self.GetSecondWindow())
 
578
 
 
579
    def OnZoomChangedSecondMap(self):
 
580
        """Display region of the second window (Map) changed.
 
581
 
 
582
        Synchronize the region of the second map and re-render it.
 
583
        This is the default implementation which can be overridden.
 
584
        """
 
585
        region = self.GetSecondMap().GetCurrentRegion()
 
586
        self.GetFirstMap().region.update(region)
 
587
        self.Render(mapToRender = self.GetFirstWindow())
 
588
 
 
589
    def OnZoomIn(self, event):
 
590
        """Zoom in the map."""
 
591
        self.GetFirstWindow().SetModeZoomIn()
 
592
        self.GetSecondWindow().SetModeZoomIn()
 
593
 
 
594
    def OnZoomOut(self, event):
 
595
        """Zoom out the map."""
 
596
        self.GetFirstWindow().SetModeZoomOut()
 
597
        self.GetSecondWindow().SetModeZoomOut()
 
598
        
 
599
    def OnPan(self, event):
 
600
        """Panning, set mouse to pan"""
 
601
        self.GetFirstWindow().SetModePan()
 
602
        self.GetSecondWindow().SetModePan()
 
603
 
 
604
    def OnPointer(self, event):
 
605
        """Set pointer mode (dragging overlays)"""
 
606
        self.GetFirstWindow().SetModePointer()
 
607
        self.GetSecondWindow().SetModePointer()
 
608
 
 
609
    def OnQuery(self, event):
 
610
        """Set query mode"""
 
611
        self.GetFirstWindow().SetModeQuery()
 
612
        self.GetSecondWindow().SetModeQuery()
 
613
 
 
614
    def OnRender(self, event):
 
615
        """Re-render map composition (each map layer)
 
616
        """
 
617
        self.Render(mapToRender = self.GetFirstWindow())
 
618
        self.Render(mapToRender = self.GetSecondWindow())
 
619
    
 
620
    def Render(self, mapToRender):
 
621
        """Re-render map composition"""
 
622
        mapToRender.UpdateMap(render = True,
 
623
                              renderVector = mapToRender == self.GetFirstWindow())
 
624
        
 
625
        # update statusbar
 
626
        self.StatusbarUpdate()
 
627
        
 
628
    def OnErase(self, event):
 
629
        """Erase the canvas
 
630
        """
 
631
        self.Erase(mapToErase = self.GetFirstWindow())
 
632
        self.Erase(mapToErase = self.GetSecondWindow())
 
633
        
 
634
    def Erase(self, mapToErase):
 
635
        """Erase the canvas
 
636
        """
 
637
        mapToErase.EraseMap()
 
638
        
 
639
    def OnDraw(self, event):
 
640
        """Re-display current map composition
 
641
        """
 
642
        self.Draw(mapToDraw = self.GetFirstWindow())
 
643
        self.Draw(mapToDraw = self.GetSecondWindow())
 
644
        
 
645
    def Draw(self, mapToDraw):
 
646
        """Re-display current map composition
 
647
        """
 
648
        mapToDraw.UpdateMap(render = False)