|
GRASS Programmer's Manual
6.5.svn(2012)-r51648
|
00001 """! 00002 @package mapdisp.statusbar 00003 00004 @brief Classes for statusbar management 00005 00006 Classes: 00007 - statusbar::SbException 00008 - statusbar::SbManager 00009 - statusbar::SbItem 00010 - statusbar::SbRender 00011 - statusbar::SbShowRegion 00012 - statusbar::SbAlignExtent 00013 - statusbar::SbResolution 00014 - statusbar::SbMapScale 00015 - statusbar::SbGoTo 00016 - statusbar::SbProjection 00017 - statusbar::SbMask 00018 - statusbar::SbTextItem 00019 - statusbar::SbDisplayGeometry 00020 - statusbar::SbCoordinates 00021 - statusbar::SbRegionExtent 00022 - statusbar::SbCompRegionExtent 00023 - statusbar::SbProgress 00024 00025 (C) 2006-2011 by the GRASS Development Team 00026 00027 This program is free software under the GNU General Public License 00028 (>=v2). Read the file COPYING that comes with GRASS for details. 00029 00030 @author Vaclav Petras <wenzeslaus gmail.com> 00031 @author Anna Kratochvilova <kratochanna gmail.com> 00032 """ 00033 00034 import wx 00035 00036 from core import utils 00037 from core.gcmd import GMessage, RunCommand 00038 from core.settings import UserSettings 00039 00040 from grass.script import core as grass 00041 00042 class SbException: 00043 """! Exception class used in SbManager and SbItems""" 00044 def __init__(self, message): 00045 self.message = message 00046 def __str__(self): 00047 return self.message 00048 00049 00050 class SbManager: 00051 """!Statusbar manager for wx.Statusbar and SbItems. 00052 00053 Statusbar manager manages items added by AddStatusbarItem method. 00054 Provides progress bar (SbProgress) and choice (wx.Choice). 00055 Items with position 0 are shown according to choice selection. 00056 Only one item of the same class is supposed to be in statusbar. 00057 Manager user have to create statusbar on his own, add items to manager 00058 and call Update method to show particular widgets. 00059 User settings (group = 'display', key = 'statusbarMode', subkey = 'selection') 00060 are taken into account. 00061 00062 @todo generalize access to UserSettings (specify group, etc.) 00063 @todo add GetMode method using name instead of index 00064 """ 00065 def __init__(self, mapframe, statusbar): 00066 """!Connects manager to statusbar 00067 00068 Creates choice and progress bar. 00069 """ 00070 self.mapFrame = mapframe 00071 self.statusbar = statusbar 00072 00073 self.choice = wx.Choice(self.statusbar, wx.ID_ANY) 00074 00075 self.choice.Bind(wx.EVT_CHOICE, self.OnToggleStatus) 00076 00077 self.statusbarItems = dict() 00078 00079 self._postInitialized = False 00080 00081 self.progressbar = SbProgress(self.mapFrame, self.statusbar) 00082 00083 self._hiddenItems = {} 00084 00085 def SetProperty(self, name, value): 00086 """!Sets property represented by one of contained SbItems 00087 00088 @param name name of SbItem (from name attribute) 00089 @param value value to be set 00090 """ 00091 self.statusbarItems[name].SetValue(value) 00092 00093 def GetProperty(self, name): 00094 """!Returns property represented by one of contained SbItems 00095 00096 @param name name of SbItem (from name attribute) 00097 """ 00098 return self.statusbarItems[name].GetValue() 00099 00100 def HasProperty(self, name): 00101 """!Checks whether property is represented by one of contained SbItems 00102 00103 @param name name of SbItem (from name attribute) 00104 00105 @returns True if particular SbItem is contained, False otherwise 00106 """ 00107 if name in self.statusbarItems: 00108 return True 00109 return False 00110 00111 def AddStatusbarItem(self, item): 00112 """!Adds item to statusbar 00113 00114 If item position is 0, item is managed by choice. 00115 00116 @see AddStatusbarItemsByClass 00117 """ 00118 self.statusbarItems[item.name] = item 00119 if item.GetPosition() == 0: 00120 self.choice.Append(item.label, clientData = item) #attrError? 00121 00122 def AddStatusbarItemsByClass(self, itemClasses, **kwargs): 00123 """!Adds items to statusbar 00124 00125 @param itemClasses list of classes of items to be add 00126 @param kwargs SbItem constructor parameters 00127 00128 @see AddStatusbarItem 00129 """ 00130 for Item in itemClasses: 00131 item = Item(**kwargs) 00132 self.AddStatusbarItem(item) 00133 00134 def HideStatusbarChoiceItemsByClass(self, itemClasses): 00135 """!Hides items showed in choice 00136 00137 Hides items with position 0 (items showed in choice) by removing 00138 them from choice. 00139 00140 @param itemClasses list of classes of items to be hided 00141 00142 @see ShowStatusbarChoiceItemsByClass 00143 @todo consider adding similar function which would take item names 00144 """ 00145 index = [] 00146 for itemClass in itemClasses: 00147 for i in range(0, self.choice.GetCount() - 1): 00148 item = self.choice.GetClientData(i) 00149 if item.__class__ == itemClass: 00150 index.append(i) 00151 self._hiddenItems[i] = item 00152 # must be sorted in reverse order to be removed correctly 00153 for i in sorted(index, reverse = True): 00154 self.choice.Delete(i) 00155 00156 def ShowStatusbarChoiceItemsByClass(self, itemClasses): 00157 """!Shows items showed in choice 00158 00159 Shows items with position 0 (items showed in choice) by adding 00160 them to choice. 00161 Items are restored in their old positions. 00162 00163 @param itemClasses list of classes of items to be showed 00164 00165 @see HideStatusbarChoiceItemsByClass 00166 """ 00167 # must be sorted to be inserted correctly 00168 for pos in sorted(self._hiddenItems.keys()): 00169 item = self._hiddenItems[pos] 00170 if item.__class__ in itemClasses: 00171 self.choice.Insert(item.label, pos, item) 00172 00173 def ShowItem(self, itemName): 00174 """!Invokes showing of particular item 00175 00176 @see Update 00177 """ 00178 self.statusbarItems[itemName].Show() 00179 00180 def _postInit(self): 00181 """!Post-initialization method 00182 00183 It sets internal user settings, 00184 set choice's selection (from user settings) and does reposition. 00185 It needs choice filled by items. 00186 it is called automatically. 00187 """ 00188 UserSettings.Set(group = 'display', 00189 key = 'statusbarMode', 00190 subkey = 'choices', 00191 value = self.choice.GetItems(), 00192 internal = True) 00193 00194 self.choice.SetSelection(UserSettings.Get(group = 'display', 00195 key = 'statusbarMode', 00196 subkey = 'selection')) 00197 self.Reposition() 00198 00199 self._postInitialized = True 00200 00201 def Update(self): 00202 """!Updates statusbar 00203 00204 It always updates mask. 00205 """ 00206 if not self._postInitialized: 00207 self._postInit() 00208 00209 for item in self.statusbarItems.values(): 00210 if item.GetPosition() == 0: 00211 item.Hide() 00212 else: 00213 item.Update() # mask, render 00214 00215 if self.choice.GetCount() > 0: 00216 item = self.choice.GetClientData(self.choice.GetSelection()) 00217 item.Update() 00218 00219 def Reposition(self): 00220 """!Reposition items in statusbar 00221 00222 Set positions to all items managed by statusbar manager. 00223 It should not be necessary to call it manually. 00224 """ 00225 00226 widgets = [] 00227 for item in self.statusbarItems.values(): 00228 widgets.append((item.GetPosition(), item.GetWidget())) 00229 00230 widgets.append((1, self.choice)) 00231 widgets.append((0, self.progressbar.GetWidget())) 00232 00233 for idx, win in widgets: 00234 if not win: 00235 continue 00236 rect = self.statusbar.GetFieldRect(idx) 00237 if idx == 0: # show region / mapscale / process bar 00238 # -> size 00239 wWin, hWin = win.GetBestSize() 00240 if win == self.progressbar.GetWidget(): 00241 wWin = rect.width - 6 00242 # -> position 00243 # if win == self.statusbarWin['region']: 00244 # x, y = rect.x + rect.width - wWin, rect.y - 1 00245 # align left 00246 # else: 00247 x, y = rect.x + 3, rect.y - 1 00248 w, h = wWin, rect.height + 2 00249 else: # choice || auto-rendering 00250 x, y = rect.x, rect.y - 1 00251 w, h = rect.width, rect.height + 2 00252 if idx == 2: # mask 00253 x += 5 00254 y += 4 00255 elif idx == 3: # render 00256 x += 5 00257 win.SetPosition((x, y)) 00258 win.SetSize((w, h)) 00259 00260 def GetProgressBar(self): 00261 """!Returns progress bar""" 00262 return self.progressbar 00263 00264 def OnToggleStatus(self, event): 00265 """!Toggle status text 00266 """ 00267 self.Update() 00268 00269 def SetMode(self, modeIndex): 00270 """!Sets current mode 00271 00272 Mode is usually driven by user through choice. 00273 """ 00274 self.choice.SetSelection(modeIndex) 00275 00276 def GetMode(self): 00277 """!Returns current mode""" 00278 return self.choice.GetSelection() 00279 00280 class SbItem: 00281 """!Base class for statusbar items. 00282 00283 Each item represents functionality (or action) controlled by statusbar 00284 and related to MapFrame. 00285 One item is usually connected with one widget but it is not necessary. 00286 Item can represent property (depends on manager). 00287 Items are not widgets but can provide interface to them. 00288 Items usually has requirements to MapFrame instance 00289 (specified as MapFrame.methodname or MapWindow.methodname). 00290 00291 @todo consider externalizing position (see SbProgress use in SbManager) 00292 """ 00293 def __init__(self, mapframe, statusbar, position = 0): 00294 """! 00295 00296 @param mapframe instance of class with MapFrame interface 00297 @param statusbar statusbar instance (wx.Statusbar) 00298 @param position item position in statusbar 00299 00300 @todo rewrite Update also in derived classes to take in account item position 00301 """ 00302 self.mapFrame = mapframe 00303 self.statusbar = statusbar 00304 self.position = position 00305 00306 def Show(self): 00307 """!Invokes showing of underlying widget. 00308 00309 In derived classes it can do what is appropriate for it, 00310 e.g. showing text on statusbar (only). 00311 """ 00312 self.widget.Show() 00313 00314 def Hide(self): 00315 self.widget.Hide() 00316 00317 def SetValue(self, value): 00318 self.widget.SetValue(value) 00319 00320 def GetValue(self): 00321 return self.widget.GetValue() 00322 00323 def GetPosition(self): 00324 return self.position 00325 00326 def GetWidget(self): 00327 """!Returns underlaying winget. 00328 00329 @return widget or None if doesn't exist 00330 """ 00331 return self.widget 00332 00333 def _update(self, longHelp): 00334 """!Default implementation for Update method. 00335 00336 @param longHelp True to enable long help (help from toolbars) 00337 """ 00338 self.statusbar.SetStatusText("", 0) 00339 self.Show() 00340 self.mapFrame.StatusbarEnableLongHelp(longHelp) 00341 00342 def Update(self): 00343 """!Called when statusbar action is activated (e.g. through wx.Choice). 00344 """ 00345 self._update(longHelp = False) 00346 00347 class SbRender(SbItem): 00348 """!Checkbox to enable and disable auto-rendering. 00349 00350 Requires MapFrame.OnRender method. 00351 """ 00352 def __init__(self, mapframe, statusbar, position = 0): 00353 SbItem.__init__(self, mapframe, statusbar, position) 00354 self.name = 'render' 00355 00356 self.widget = wx.CheckBox(parent = self.statusbar, id = wx.ID_ANY, 00357 label = _("Render")) 00358 00359 self.widget.SetValue(UserSettings.Get(group = 'display', 00360 key = 'autoRendering', 00361 subkey = 'enabled')) 00362 self.widget.Hide() 00363 self.widget.SetToolTip(wx.ToolTip (_("Enable/disable auto-rendering"))) 00364 00365 self.widget.Bind(wx.EVT_CHECKBOX, self.OnToggleRender) 00366 00367 def OnToggleRender(self, event): 00368 # (other items should call self.mapFrame.IsAutoRendered()) 00369 if self.GetValue(): 00370 self.mapFrame.OnRender(None) 00371 00372 def Update(self): 00373 self.Show() 00374 00375 class SbShowRegion(SbItem): 00376 """!Checkbox to enable and disable showing of computational region. 00377 00378 Requires MapFrame.OnRender, MapFrame.IsAutoRendered, MapFrame.GetWindow. 00379 Expects that instance returned by MapFrame.GetWindow will handle 00380 regionCoords attribute. 00381 """ 00382 def __init__(self, mapframe, statusbar, position = 0): 00383 SbItem.__init__(self, mapframe, statusbar, position) 00384 self.name = 'region' 00385 self.label = _("Show comp. extent") 00386 00387 self.widget = wx.CheckBox(parent = self.statusbar, id = wx.ID_ANY, 00388 label = _("Show computational extent")) 00389 00390 self.widget.SetValue(False) 00391 self.widget.Hide() 00392 self.widget.SetToolTip(wx.ToolTip (_("Show/hide computational " 00393 "region extent (set with g.region). " 00394 "Display region drawn as a blue box inside the " 00395 "computational region, " 00396 "computational region inside a display region " 00397 "as a red box)."))) 00398 00399 self.widget.Bind(wx.EVT_CHECKBOX, self.OnToggleShowRegion) 00400 00401 def OnToggleShowRegion(self, event): 00402 """!Shows/Hides extent (comp. region) in map canvas. 00403 00404 Shows or hides according to checkbox value. 00405 """ 00406 if self.widget.GetValue(): 00407 # show extent 00408 self.mapFrame.GetWindow().regionCoords = [] 00409 elif hasattr(self.mapFrame.GetWindow(), 'regionCoords'): 00410 del self.mapFrame.GetWindow().regionCoords 00411 00412 # redraw map if auto-rendering is enabled 00413 if self.mapFrame.IsAutoRendered(): 00414 self.mapFrame.OnRender(None) 00415 00416 def SetValue(self, value): 00417 SbItem.SetValue(self, value) 00418 if value: 00419 self.mapFrame.GetWindow().regionCoords = [] 00420 elif hasattr(self.mapFrame.GetWindow(), 'regionCoords'): 00421 del self.mapFrame.GetWindow().regionCoords 00422 00423 class SbAlignExtent(SbItem): 00424 """!Checkbox to select zoom behavior. 00425 00426 Used by BufferedWindow (through MapFrame property). 00427 See tooltip for explanation. 00428 """ 00429 def __init__(self, mapframe, statusbar, position = 0): 00430 SbItem.__init__(self, mapframe, statusbar, position) 00431 self.name = 'alignExtent' 00432 self.label = _("Display mode") 00433 00434 self.widget = wx.CheckBox(parent = self.statusbar, id = wx.ID_ANY, 00435 label = _("Align region extent based on display size")) 00436 00437 self.widget.SetValue(UserSettings.Get(group = 'display', key = 'alignExtent', subkey = 'enabled')) 00438 self.widget.Hide() 00439 self.widget.SetToolTip(wx.ToolTip (_("Align region extent based on display " 00440 "size from center point. " 00441 "Default value for new map displays can " 00442 "be set up in 'User GUI settings' dialog."))) 00443 00444 class SbResolution(SbItem): 00445 """!Checkbox to select used display resolution. 00446 00447 Requires MapFrame.OnRender method. 00448 """ 00449 def __init__(self, mapframe, statusbar, position = 0): 00450 SbItem.__init__(self, mapframe, statusbar, position) 00451 self.name = 'resolution' 00452 self.label = _("Display resolution") 00453 00454 self.widget = wx.CheckBox(parent = self.statusbar, id = wx.ID_ANY, 00455 label = _("Constrain display resolution to computational settings")) 00456 00457 self.widget.SetValue(UserSettings.Get(group = 'display', key = 'compResolution', subkey = 'enabled')) 00458 self.widget.Hide() 00459 self.widget.SetToolTip(wx.ToolTip (_("Constrain display resolution " 00460 "to computational region settings. " 00461 "Default value for new map displays can " 00462 "be set up in 'User GUI settings' dialog."))) 00463 00464 self.widget.Bind(wx.EVT_CHECKBOX, self.OnToggleUpdateMap) 00465 00466 def OnToggleUpdateMap(self, event): 00467 """!Update display when toggle display mode 00468 """ 00469 # redraw map if auto-rendering is enabled 00470 if self.mapFrame.IsAutoRendered(): 00471 self.mapFrame.OnRender(None) 00472 00473 00474 class SbMapScale(SbItem): 00475 """!Editable combobox to get/set current map scale. 00476 00477 Requires MapFrame.GetMapScale, MapFrame.SetMapScale 00478 and MapFrame.GetWindow (and GetWindow().UpdateMap()). 00479 """ 00480 def __init__(self, mapframe, statusbar, position = 0): 00481 SbItem.__init__(self, mapframe, statusbar, position) 00482 self.name = 'mapscale' 00483 self.label = _("Map scale") 00484 00485 self.widget = wx.ComboBox(parent = self.statusbar, id = wx.ID_ANY, 00486 style = wx.TE_PROCESS_ENTER, 00487 size = (150, -1)) 00488 00489 self.widget.SetItems(['1:1000', 00490 '1:5000', 00491 '1:10000', 00492 '1:25000', 00493 '1:50000', 00494 '1:100000', 00495 '1:1000000']) 00496 self.widget.Hide() 00497 self.widget.SetToolTip(wx.ToolTip (_("As everyone's monitors and resolutions " 00498 "are set differently these values are not " 00499 "true map scales, but should get you into " 00500 "the right neighborhood."))) 00501 00502 self.widget.Bind(wx.EVT_TEXT_ENTER, self.OnChangeMapScale) 00503 self.widget.Bind(wx.EVT_COMBOBOX, self.OnChangeMapScale) 00504 00505 self.lastMapScale = None 00506 00507 def Update(self): 00508 scale = self.mapFrame.GetMapScale() 00509 self.statusbar.SetStatusText("") 00510 try: 00511 self.SetValue("1:%ld" % (scale + 0.5)) 00512 except TypeError: 00513 pass # FIXME, why this should happen? 00514 00515 self.lastMapScale = scale 00516 self.Show() 00517 00518 # disable long help 00519 self.mapFrame.StatusbarEnableLongHelp(False) 00520 00521 def OnChangeMapScale(self, event): 00522 """!Map scale changed by user 00523 """ 00524 scale = event.GetString() 00525 00526 try: 00527 if scale[:2] != '1:': 00528 raise ValueError 00529 value = int(scale[2:]) 00530 except ValueError: 00531 self.SetValue('1:%ld' % int(self.lastMapScale)) 00532 return 00533 00534 self.mapFrame.SetMapScale(value) 00535 00536 # redraw a map 00537 self.mapFrame.GetWindow().UpdateMap() 00538 self.GetWidget().SetFocus() 00539 00540 00541 class SbGoTo(SbItem): 00542 """!Textctrl to set coordinates which to focus on. 00543 00544 Requires MapFrame.GetWindow, MapWindow.GoTo method. 00545 """ 00546 00547 def __init__(self, mapframe, statusbar, position = 0): 00548 SbItem.__init__(self, mapframe, statusbar, position) 00549 self.name = 'goto' 00550 self.label = _("Go to") 00551 00552 self.widget = wx.TextCtrl(parent = self.statusbar, id = wx.ID_ANY, 00553 value = "", style = wx.TE_PROCESS_ENTER, 00554 size = (300, -1)) 00555 00556 self.widget.Hide() 00557 00558 self.widget.Bind(wx.EVT_TEXT_ENTER, self.OnGoTo) 00559 00560 def ReprojectENToMap(self, e, n, useDefinedProjection): 00561 """!Reproject east, north from user defined projection 00562 00563 @param e,n coordinate (for DMS string, else float or string) 00564 @param useDefinedProjection projection defined by user in settings dialog 00565 00566 @throws SbException if useDefinedProjection is True and projection is not defined in UserSettings 00567 """ 00568 if useDefinedProjection: 00569 settings = UserSettings.Get(group = 'projection', key = 'statusbar', subkey = 'proj4') 00570 if not settings: 00571 raise SbException(_("Projection not defined (check the settings)")) 00572 else: 00573 # reproject values 00574 projIn = settings 00575 projOut = RunCommand('g.proj', 00576 flags = 'jf', 00577 read = True) 00578 proj = projIn.split(' ')[0].split('=')[1] 00579 if proj in ('ll', 'latlong', 'longlat'): 00580 e, n = utils.DMS2Deg(e, n) 00581 proj, coord1 = utils.ReprojectCoordinates(coord = (e, n), 00582 projIn = projIn, 00583 projOut = projOut, flags = 'd') 00584 e, n = coord1 00585 else: 00586 e, n = float(e), float(n) 00587 proj, coord1 = utils.ReprojectCoordinates(coord = (e, n), 00588 projIn = projIn, 00589 projOut = projOut, flags = 'd') 00590 e, n = coord1 00591 elif self.mapFrame.GetMap().projinfo['proj'] == 'll': 00592 e, n = utils.DMS2Deg(e, n) 00593 else: 00594 e, n = float(e), float(n) 00595 return e, n 00596 00597 def OnGoTo(self, event): 00598 """!Go to position 00599 """ 00600 try: 00601 e, n = self.GetValue().split(';') 00602 e, n = self.ReprojectENToMap(e, n, self.mapFrame.GetProperty('projection')) 00603 self.mapFrame.GetWindow().GoTo(e, n) 00604 self.widget.SetFocus() 00605 except ValueError: 00606 # FIXME: move this code to MapWindow/BufferedWindow/MapFrame 00607 region = self.mapFrame.GetMap().GetCurrentRegion() 00608 precision = int(UserSettings.Get(group = 'projection', key = 'format', 00609 subkey = 'precision')) 00610 format = UserSettings.Get(group = 'projection', key = 'format', 00611 subkey = 'll') 00612 if self.mapFrame.GetMap().projinfo['proj'] == 'll' and format == 'DMS': 00613 self.SetValue("%s" % utils.Deg2DMS(region['center_easting'], 00614 region['center_northing'], 00615 precision = precision)) 00616 else: 00617 self.SetValue("%.*f; %.*f" % \ 00618 (precision, region['center_easting'], 00619 precision, region['center_northing'])) 00620 except SbException, e: 00621 # FIXME: this may be useless since statusbar update checks user defined projection and this exception raises when user def proj does not exists 00622 self.statusbar.SetStatusText(str(e), 0) 00623 00624 def GetCenterString(self, map): 00625 """!Get current map center in appropriate format""" 00626 region = map.GetCurrentRegion() 00627 precision = int(UserSettings.Get(group = 'projection', key = 'format', 00628 subkey = 'precision')) 00629 format = UserSettings.Get(group = 'projection', key = 'format', 00630 subkey = 'll') 00631 projection = UserSettings.Get(group='projection', key='statusbar', subkey='proj4') 00632 00633 if self.mapFrame.GetProperty('projection'): 00634 if not projection: 00635 raise SbException(_("Projection not defined (check the settings)")) 00636 else: 00637 proj, coord = utils.ReprojectCoordinates(coord = (region['center_easting'], 00638 region['center_northing']), 00639 projOut = projection, 00640 flags = 'd') 00641 if coord: 00642 if proj in ('ll', 'latlong', 'longlat') and format == 'DMS': 00643 return "%s" % utils.Deg2DMS(coord[0], 00644 coord[1], 00645 precision = precision) 00646 else: 00647 return "%.*f; %.*f" % (precision, coord[0], precision, coord[1]) 00648 else: 00649 raise SbException(_("Error in projection (check the settings)")) 00650 else: 00651 if self.mapFrame.GetMap().projinfo['proj'] == 'll' and format == 'DMS': 00652 return "%s" % utils.Deg2DMS(region['center_easting'], region['center_northing'], 00653 precision = precision) 00654 else: 00655 return "%.*f; %.*f" % (precision, region['center_easting'], precision, region['center_northing']) 00656 00657 00658 def SetCenter(self): 00659 """!Set current map center as item value""" 00660 center = self.GetCenterString(self.mapFrame.GetMap()) 00661 self.SetValue(center) 00662 00663 def Update(self): 00664 self.statusbar.SetStatusText("") 00665 00666 try: 00667 self.SetCenter() 00668 self.Show() 00669 except SbException, e: 00670 self.statusbar.SetStatusText(str(e), 0) 00671 00672 # disable long help 00673 self.mapFrame.StatusbarEnableLongHelp(False) 00674 00675 00676 class SbProjection(SbItem): 00677 """!Checkbox to enable user defined projection (can be set in settings)""" 00678 def __init__(self, mapframe, statusbar, position = 0): 00679 SbItem.__init__(self, mapframe, statusbar, position) 00680 self.name = 'projection' 00681 self.label = _("Projection") 00682 00683 self.defaultLabel = _("Use defined projection") 00684 00685 self.widget = wx.CheckBox(parent = self.statusbar, id = wx.ID_ANY, 00686 label = self.defaultLabel) 00687 00688 self.widget.SetValue(False) 00689 00690 # necessary? 00691 size = self.widget.GetSize() 00692 self.widget.SetMinSize((size[0] + 150, size[1])) 00693 00694 self.widget.Hide() 00695 self.widget.SetToolTip(wx.ToolTip (_("Reproject coordinates displayed " 00696 "in the statusbar. Projection can be " 00697 "defined in GUI preferences dialog " 00698 "(tab 'Projection')"))) 00699 00700 def Update(self): 00701 self.statusbar.SetStatusText("") 00702 epsg = UserSettings.Get(group = 'projection', key = 'statusbar', subkey = 'epsg') 00703 if epsg: 00704 label = '%s (EPSG: %s)' % (self.defaultLabel, epsg) 00705 self.widget.SetLabel(label) 00706 else: 00707 self.widget.SetLabel(self.defaultLabel) 00708 self.Show() 00709 00710 # disable long help 00711 self.mapFrame.StatusbarEnableLongHelp(False) 00712 00713 00714 class SbMask(SbItem): 00715 """!StaticText to show whether mask is activated.""" 00716 def __init__(self, mapframe, statusbar, position = 0): 00717 SbItem.__init__(self, mapframe, statusbar, position) 00718 self.name = 'mask' 00719 00720 self.widget = wx.StaticText(parent = self.statusbar, id = wx.ID_ANY, label = _('MASK')) 00721 self.widget.SetForegroundColour(wx.Colour(255, 0, 0)) 00722 self.widget.Hide() 00723 00724 def Update(self): 00725 if grass.find_file(name = 'MASK', element = 'cell')['name']: 00726 self.Show() 00727 else: 00728 self.Hide() 00729 00730 class SbTextItem(SbItem): 00731 """!Base class for items without widgets. 00732 00733 Only sets statusbar text. 00734 """ 00735 def __init__(self, mapframe, statusbar, position = 0): 00736 SbItem.__init__(self, mapframe, statusbar, position) 00737 00738 self.text = None 00739 00740 def Show(self): 00741 self.statusbar.SetStatusText(self.GetValue(), self.position) 00742 00743 def Hide(self): 00744 self.statusbar.SetStatusText("", self.position) 00745 00746 def SetValue(self, value): 00747 self.text = value 00748 00749 def GetValue(self): 00750 return self.text 00751 00752 def GetWidget(self): 00753 return None 00754 00755 def Update(self): 00756 self._update(longHelp = True) 00757 00758 class SbDisplayGeometry(SbTextItem): 00759 """!Show current display resolution.""" 00760 def __init__(self, mapframe, statusbar, position = 0): 00761 SbTextItem.__init__(self, mapframe, statusbar, position) 00762 self.name = 'displayGeometry' 00763 self.label = _("Display geometry") 00764 00765 def Show(self): 00766 region = self.mapFrame.GetMap().GetCurrentRegion() 00767 self.SetValue("rows=%d; cols=%d; nsres=%.2f; ewres=%.2f" % 00768 (region["rows"], region["cols"], 00769 region["nsres"], region["ewres"])) 00770 SbTextItem.Show(self) 00771 00772 class SbCoordinates(SbTextItem): 00773 """!Show map coordinates when mouse moves. 00774 00775 Requires MapWindow.GetLastEN method.""" 00776 def __init__(self, mapframe, statusbar, position = 0): 00777 SbTextItem.__init__(self, mapframe, statusbar, position) 00778 self.name = 'coordinates' 00779 self.label = _("Coordinates") 00780 00781 def Show(self): 00782 precision = int(UserSettings.Get(group = 'projection', key = 'format', 00783 subkey = 'precision')) 00784 format = UserSettings.Get(group = 'projection', key = 'format', 00785 subkey = 'll') 00786 projection = self.mapFrame.GetProperty('projection') 00787 try: 00788 e, n = self.mapFrame.GetWindow().GetLastEN() 00789 self.SetValue(self.ReprojectENFromMap(e, n, projection, precision, format)) 00790 except SbException, e: 00791 self.SetValue(e) 00792 except TypeError, e: 00793 self.SetValue("") 00794 except AttributeError: 00795 self.SetValue("") # during initialization MapFrame has no MapWindow 00796 SbTextItem.Show(self) 00797 00798 def ReprojectENFromMap(self, e, n, useDefinedProjection, precision, format): 00799 """!Reproject east, north to user defined projection. 00800 00801 @param e,n coordinate 00802 00803 @throws SbException if useDefinedProjection is True and projection is not defined in UserSettings 00804 """ 00805 if useDefinedProjection: 00806 settings = UserSettings.Get(group = 'projection', key = 'statusbar', subkey = 'proj4') 00807 if not settings: 00808 raise SbException(_("Projection not defined (check the settings)")) 00809 else: 00810 # reproject values 00811 proj, coord = utils.ReprojectCoordinates(coord = (e, n), 00812 projOut = settings, 00813 flags = 'd') 00814 if coord: 00815 e, n = coord 00816 if proj in ('ll', 'latlong', 'longlat') and format == 'DMS': 00817 return utils.Deg2DMS(e, n, precision = precision) 00818 else: 00819 return "%.*f; %.*f" % (precision, e, precision, n) 00820 else: 00821 raise SbException(_("Error in projection (check the settings)")) 00822 else: 00823 if self.mapFrame.GetMap().projinfo['proj'] == 'll' and format == 'DMS': 00824 return utils.Deg2DMS(e, n, precision = precision) 00825 else: 00826 return "%.*f; %.*f" % (precision, e, precision, n) 00827 00828 class SbRegionExtent(SbTextItem): 00829 """!Shows current display region""" 00830 def __init__(self, mapframe, statusbar, position = 0): 00831 SbTextItem.__init__(self, mapframe, statusbar, position) 00832 self.name = 'displayRegion' 00833 self.label = _("Extent") 00834 00835 def Show(self): 00836 precision = int(UserSettings.Get(group = 'projection', key = 'format', 00837 subkey = 'precision')) 00838 format = UserSettings.Get(group = 'projection', key = 'format', 00839 subkey = 'll') 00840 projection = self.mapFrame.GetProperty('projection') 00841 region = self._getRegion() 00842 try: 00843 regionReprojected = self.ReprojectRegionFromMap(region, projection, precision, format) 00844 self.SetValue(regionReprojected) 00845 except SbException, e: 00846 self.SetValue(e) 00847 SbTextItem.Show(self) 00848 00849 def _getRegion(self): 00850 """!Get current display region""" 00851 return self.mapFrame.GetMap().GetCurrentRegion() # display region 00852 00853 def _formatRegion(self, w, e, s, n, nsres, ewres, precision = None): 00854 """!Format display region string for statusbar 00855 00856 @param nsres,ewres unused 00857 """ 00858 if precision is not None: 00859 return "%.*f - %.*f, %.*f - %.*f" % (precision, w, precision, e, 00860 precision, s, precision, n) 00861 else: 00862 return "%s - %s, %s - %s" % (w, e, s, n) 00863 00864 00865 def ReprojectRegionFromMap(self, region, useDefinedProjection, precision, format): 00866 """!Reproject region values 00867 00868 @todo reorganize this method to remove code useful only for derived class SbCompRegionExtent 00869 """ 00870 if useDefinedProjection: 00871 settings = UserSettings.Get(group = 'projection', key = 'statusbar', subkey = 'proj4') 00872 00873 if not settings: 00874 raise SbException(_("Projection not defined (check the settings)")) 00875 else: 00876 projOut = settings 00877 proj, coord1 = utils.ReprojectCoordinates(coord = (region["w"], region["s"]), 00878 projOut = projOut, flags = 'd') 00879 proj, coord2 = utils.ReprojectCoordinates(coord = (region["e"], region["n"]), 00880 projOut = projOut, flags = 'd') 00881 # useless, used in derived class 00882 proj, coord3 = utils.ReprojectCoordinates(coord = (0.0, 0.0), 00883 projOut = projOut, flags = 'd') 00884 proj, coord4 = utils.ReprojectCoordinates(coord = (region["ewres"], region["nsres"]), 00885 projOut = projOut, flags = 'd') 00886 if coord1 and coord2: 00887 if proj in ('ll', 'latlong', 'longlat') and format == 'DMS': 00888 w, s = utils.Deg2DMS(coord1[0], coord1[1], string = False, 00889 precision = precision) 00890 e, n = utils.Deg2DMS(coord2[0], coord2[1], string = False, 00891 precision = precision) 00892 ewres, nsres = utils.Deg2DMS(abs(coord3[0]) - abs(coord4[0]), 00893 abs(coord3[1]) - abs(coord4[1]), 00894 string = False, hemisphere = False, 00895 precision = precision) 00896 return self._formatRegion(w = w, s = s, e = e, n = n, ewres = ewres, nsres = nsres) 00897 else: 00898 w, s = coord1 00899 e, n = coord2 00900 ewres, nsres = coord3 00901 return self._formatRegion(w = w, s = s, e = e, n = n, ewres = ewres, 00902 nsres = nsres, precision = precision) 00903 else: 00904 raise SbException(_("Error in projection (check the settings)")) 00905 00906 else: 00907 if self.mapFrame.GetMap().projinfo['proj'] == 'll' and format == 'DMS': 00908 w, s = utils.Deg2DMS(region["w"], region["s"], 00909 string = False, precision = precision) 00910 e, n = utils.Deg2DMS(region["e"], region["n"], 00911 string = False, precision = precision) 00912 ewres, nsres = utils.Deg2DMS(region['ewres'], region['nsres'], 00913 string = False, precision = precision) 00914 return self._formatRegion(w = w, s = s, e = e, n = n, ewres = ewres, nsres = nsres) 00915 else: 00916 w, s = region["w"], region["s"] 00917 e, n = region["e"], region["n"] 00918 ewres, nsres = region['ewres'], region['nsres'] 00919 return self._formatRegion(w = w, s = s, e = e, n = n, ewres = ewres, 00920 nsres = nsres, precision = precision) 00921 00922 00923 class SbCompRegionExtent(SbRegionExtent): 00924 """!Shows computational region.""" 00925 def __init__(self, mapframe, statusbar, position = 0): 00926 SbRegionExtent.__init__(self, mapframe, statusbar, position) 00927 self.name = 'computationalRegion' 00928 self.label = _("Comp. region") 00929 00930 def _formatRegion(self, w, e, s, n, ewres, nsres, precision = None): 00931 """!Format computational region string for statusbar""" 00932 if precision is not None: 00933 return "%.*f - %.*f, %.*f - %.*f (%.*f, %.*f)" % (precision, w, precision, e, 00934 precision, s, precision, n, 00935 precision, ewres, precision, nsres) 00936 else: 00937 return "%s - %s, %s - %s (%s, %s)" % (w, e, s, n, ewres, nsres) 00938 00939 def _getRegion(self): 00940 """!Returns computational region.""" 00941 return self.mapFrame.GetMap().GetRegion() # computational region 00942 00943 00944 class SbProgress(SbItem): 00945 """!General progress bar to show progress. 00946 00947 Underlaying widget is wx.Gauge. 00948 """ 00949 def __init__(self, mapframe, statusbar, position = 0): 00950 SbItem.__init__(self, mapframe, statusbar, position) 00951 self.name = 'progress' 00952 00953 # on-render gauge 00954 self.widget = wx.Gauge(parent = self.statusbar, id = wx.ID_ANY, 00955 range = 0, style = wx.GA_HORIZONTAL) 00956 self.widget.Hide() 00957 00958 def GetRange(self): 00959 """!Returns progress range.""" 00960 return self.widget.GetRange() 00961 00962 def SetRange(self, range): 00963 """!Sets progress range.""" 00964 self.widget.SetRange(range) 00965 00966 00967 class SbGoToGCP(SbItem): 00968 """!SpinCtrl to select GCP to focus on 00969 00970 Requires MapFrame.GetSrcWindow, MapFrame.GetTgtWindow, MapFrame.GetListCtrl, 00971 MapFrame.GetMapCoordList. 00972 """ 00973 00974 def __init__(self, mapframe, statusbar, position = 0): 00975 SbItem.__init__(self, mapframe, statusbar, position) 00976 self.name = 'gotoGCP' 00977 self.label = _("Go to GCP No.") 00978 00979 self.widget = wx.SpinCtrl(parent = self.statusbar, id = wx.ID_ANY, 00980 value = "", min = 0) 00981 self.widget.Hide() 00982 00983 self.widget.Bind(wx.EVT_TEXT_ENTER, self.OnGoToGCP) 00984 self.widget.Bind(wx.EVT_SPINCTRL, self.OnGoToGCP) 00985 00986 def OnGoToGCP(self, event): 00987 """!Zooms to given GCP.""" 00988 GCPNo = self.GetValue() 00989 mapCoords = self.mapFrame.GetMapCoordList() 00990 00991 if GCPNo < 0 or GCPNo > len(mapCoords): # always false, spin checks it 00992 GMessage(parent = self, 00993 message = "%s 1 - %s." % (_("Valid Range:"), 00994 len(mapCoords))) 00995 return 00996 00997 if GCPNo == 0: 00998 return 00999 01000 listCtrl = self.mapFrame.GetListCtrl() 01001 01002 listCtrl.selectedkey = GCPNo 01003 listCtrl.selected = listCtrl.FindItemData(-1, GCPNo) 01004 listCtrl.render = False 01005 listCtrl.SetItemState(listCtrl.selected, 01006 wx.LIST_STATE_SELECTED, 01007 wx.LIST_STATE_SELECTED) 01008 listCtrl.render = True 01009 01010 srcWin = self.mapFrame.GetSrcWindow() 01011 tgtWin = self.mapFrame.GetTgtWindow() 01012 01013 # Source MapWindow: 01014 begin = (mapCoords[GCPNo][1], mapCoords[GCPNo][2]) 01015 begin = srcWin.Cell2Pixel(begin) 01016 end = begin 01017 srcWin.Zoom(begin, end, 0) 01018 01019 # redraw map 01020 srcWin.UpdateMap() 01021 01022 if self.mapFrame.GetShowTarget(): 01023 # Target MapWindow: 01024 begin = (mapCoords[GCPNo][3], mapCoords[GCPNo][4]) 01025 begin = tgtWin.Cell2Pixel(begin) 01026 end = begin 01027 tgtWin.Zoom(begin, end, 0) 01028 01029 # redraw map 01030 tgtWin.UpdateMap() 01031 01032 self.GetWidget().SetFocus() 01033 01034 def Update(self): 01035 self.statusbar.SetStatusText("") 01036 max = self.mapFrame.GetListCtrl().GetItemCount() 01037 if max < 1: 01038 max = 1 01039 self.widget.SetRange(0, max) 01040 self.Show() 01041 01042 # disable long help 01043 self.mapFrame.StatusbarEnableLongHelp(False) 01044 01045 class SbRMSError(SbTextItem): 01046 """!Shows RMS error. 01047 01048 Requires MapFrame.GetFwdError, MapFrame.GetBkwError. 01049 """ 01050 def __init__(self, mapframe, statusbar, position = 0): 01051 SbTextItem.__init__(self, mapframe, statusbar, position) 01052 self.name = 'RMSError' 01053 self.label = _("RMS error") 01054 01055 def Show(self): 01056 self.SetValue(_("Forward: %(forw)s, Backward: %(back)s") % 01057 { 'forw' : self.mapFrame.GetFwdError(), 01058 'back' : self.mapFrame.GetBkwError() }) 01059 SbTextItem.Show(self)