[GRASS-SVN] r57738 - in grass/trunk/gui/wxpython: core gui_core mapdisp mapwin nviz
svn_grass at osgeo.org
svn_grass at osgeo.org
Wed Sep 18 09:44:27 PDT 2013
Author: annakrat
Date: 2013-09-18 09:44:27 -0700 (Wed, 18 Sep 2013)
New Revision: 57738
Modified:
grass/trunk/gui/wxpython/core/utils.py
grass/trunk/gui/wxpython/gui_core/forms.py
grass/trunk/gui/wxpython/mapdisp/frame.py
grass/trunk/gui/wxpython/mapdisp/toolbars.py
grass/trunk/gui/wxpython/mapwin/base.py
grass/trunk/gui/wxpython/mapwin/buffered.py
grass/trunk/gui/wxpython/mapwin/decorations.py
grass/trunk/gui/wxpython/nviz/mapwindow.py
grass/trunk/gui/wxpython/nviz/wxnviz.py
Log:
wxGUI: improve decorations handling (see #2080)
Modified: grass/trunk/gui/wxpython/core/utils.py
===================================================================
--- grass/trunk/gui/wxpython/core/utils.py 2013-09-18 15:58:49 UTC (rev 57737)
+++ grass/trunk/gui/wxpython/core/utils.py 2013-09-18 16:44:27 UTC (rev 57738)
@@ -1069,6 +1069,44 @@
mainfn()
+def PilImageToWxImage(pilImage, copyAlpha = True):
+ """!Convert PIL image to wx.Image
+
+ Based on http://wiki.wxpython.org/WorkingWithImages
+ """
+ import wx
+ hasAlpha = pilImage.mode[-1] == 'A'
+ if copyAlpha and hasAlpha : # Make sure there is an alpha layer copy.
+ wxImage = wx.EmptyImage(*pilImage.size)
+ pilImageCopyRGBA = pilImage.copy()
+ pilImageCopyRGB = pilImageCopyRGBA.convert('RGB') # RGBA --> RGB
+ pilImageRgbData = pilImageCopyRGB.tostring()
+ wxImage.SetData(pilImageRgbData)
+ wxImage.SetAlphaData(pilImageCopyRGBA.tostring()[3::4]) # Create layer and insert alpha values.
+
+ else : # The resulting image will not have alpha.
+ wxImage = wx.EmptyImage(*pilImage.size)
+ pilImageCopy = pilImage.copy()
+ pilImageCopyRGB = pilImageCopy.convert('RGB') # Discard any alpha from the PIL image.
+ pilImageRgbData = pilImageCopyRGB.tostring()
+ wxImage.SetData(pilImageRgbData)
+
+ return wxImage
+
+
+def autoCropImageFromFile(filename):
+ """!Loads image from file and crops it automatically.
+
+ @param filename path to file
+ @return wx.Image instance
+ """
+ import Image
+ pilImage = Image.open(filename)
+ imageBox = pilImage.getbbox()
+ cropped = pilImage.crop(imageBox)
+ return PilImageToWxImage(cropped, copyAlpha=True)
+
+
def isInRegion(regionA, regionB):
"""!Tests if 'regionA' is inside of 'regionB'.
Modified: grass/trunk/gui/wxpython/gui_core/forms.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/forms.py 2013-09-18 15:58:49 UTC (rev 57737)
+++ grass/trunk/gui/wxpython/gui_core/forms.py 2013-09-18 16:44:27 UTC (rev 57738)
@@ -748,7 +748,7 @@
'MapWindow'):
# display decorations and
# pressing OK or cancel after setting layer properties
- if self.task.name in ['d.barscale','d.legend','d.histogram'] \
+ if self.task.name in ['d.barscale','d.legend', 'd.northarrow', 'd.histogram'] \
or len(self.parent.GetLayerInfo(self.layer, key = 'cmd')) >= 1:
self.Hide()
# canceled layer with nothing set
@@ -1063,12 +1063,12 @@
cb = ColorTablesComboBox(parent=which_panel, value=p.get('default',''),
size=globalvar.DIALOG_COMBOBOX_SIZE,
choices=valuelist)
- elif self.task.name == 'd.barscale' and p['name'] in ('style', 'north_arrow'):
- if p['name'] == 'style':
+ elif p['name'] == 'style' and self.task.name in ('d.barscale', 'd.northarrow'):
+ if self.task.name == 'd.barscale':
cb = BarscalesComboBox(parent=which_panel, value=p.get('default',''),
size=globalvar.DIALOG_COMBOBOX_SIZE,
choices=valuelist)
- elif p['name'] == 'north_arrow':
+ elif self.task.name == 'd.northarrow':
cb = NArrowsComboBox(parent=which_panel, value=p.get('default',''),
size=globalvar.DIALOG_COMBOBOX_SIZE,
choices=valuelist)
Modified: grass/trunk/gui/wxpython/mapdisp/frame.py
===================================================================
--- grass/trunk/gui/wxpython/mapdisp/frame.py 2013-09-18 15:58:49 UTC (rev 57737)
+++ grass/trunk/gui/wxpython/mapdisp/frame.py 2013-09-18 16:44:27 UTC (rev 57738)
@@ -50,14 +50,14 @@
from mapwin.base import MapWindowProperties
from gui_core.query import QueryDialog, PrepareQueryResults
from mapwin.buffered import BufferedMapWindow
-from mapwin.decorations import DecorationDialog, TextLayerDialog, \
- LegendController, BarscaleController, \
- DECOR_DIALOG_LEGEND, DECOR_DIALOG_BARSCALE
+from mapwin.decorations import TextLayerDialog, \
+ LegendController, BarscaleController, ArrowController
from modules.histogram import HistogramFrame
from wxplot.histogram import HistogramPlotFrame
from wxplot.profile import ProfileFrame
from wxplot.scatter import ScatterFrame
from mapwin.analysis import ProfileController, MeasureDistanceController
+from gui_core.forms import GUI
from mapdisp import statusbar as sb
@@ -160,10 +160,12 @@
# init decoration objects
self.decorations = {}
- self.legend = LegendController(self.Map)
- self.barscale = BarscaleController(self.Map)
+ self.legend = LegendController(self.Map, self._giface)
+ self.barscale = BarscaleController(self.Map, self._giface)
+ self.arrow = ArrowController(self.Map, self._giface)
self.decorations[self.legend.id] = self.legend
self.decorations[self.barscale.id] = self.barscale
+ self.decorations[self.arrow.id] = self.arrow
self.mapWindowProperties.autoRenderChanged.connect(
lambda value:
@@ -178,6 +180,10 @@
overlays=self.decorations)
self.MapWindow2D.mapQueried.connect(self.Query)
self.MapWindow2D.overlayActivated.connect(self._activateOverlay)
+ self.MapWindow2D.overlayHidden.connect(self._hideOverlay)
+ self.MapWindow2D.overlayHidden.connect(self._hideOverlay)
+ for overlay in (self.legend, self.barscale, self.arrow):
+ overlay.overlayChanged.connect(lambda: self.MapWindow2D.UpdateMap(render=False, renderVector=False))
self._setUpMapWindow(self.MapWindow2D)
self.MapWindow2D.mouseHandlerUnregistered.connect(self.ResetPointer)
@@ -226,13 +232,9 @@
self.dialogs = {}
self.dialogs['attributes'] = None
self.dialogs['category'] = None
- self.dialogs['barscale'] = None
- self.dialogs['legend'] = None
self.dialogs['vnet'] = None
self.dialogs['query'] = None
- self.decorationDialog = None # decoration/overlays
-
self.measureDistController = None
def GetMapWindow(self):
@@ -360,6 +362,8 @@
self.MapWindow3D.ResetViewHistory()
self.MapWindow3D.UpdateView(None)
self.MapWindow3D.overlayActivated.connect(self._activateOverlay)
+ self.MapWindow3D.overlayHidden.connect(self._hideOverlay)
+ self.legend.overlayChanged.connect(lambda: self.MapWindow3D.UpdateOverlays())
else:
self.MapWindow = self.MapWindow3D
os.environ['GRASS_REGION'] = self.Map.SetRegion(windres = True, windres3 = True)
@@ -908,34 +912,50 @@
win.Update()
def _activateOverlay(self, overlayId):
- """!Launch decoratio dialog according to overlay id.
+ """!Launch decoration dialog according to overlay id.
@param overlayId id of overlay
"""
if overlayId > 100:
self.OnAddText(None)
elif overlayId == 0:
- self.AddBarscale()
+ self.AddLegend(showDialog=True)
elif overlayId == 1:
- self.AddLegend()
+ self.AddBarscale(showDialog=True)
+ elif overlayId == 2:
+ self.AddArrow(showDialog=True)
- def AddBarscale(self, cmd = None, showDialog = True):
- """!Handler for scale/arrow map decoration menu selection.
+ def _hideOverlay(self, overlayId):
+ """!Hide overlay.
+
+ @param overlayId id of overlay
"""
+ self.decorations[overlayId].Hide()
+
+ def AddBarscale(self, cmd=None, showDialog=None):
+ """!Handler for scale bar map decoration menu selection."""
+ if self.IsPaneShown('3d'):
+ self.MapWindow3D.SetDrawScalebar((70, 70))
+ return
+
+ if self.barscale.IsShown() and showDialog is None:
+ self.barscale.Hide()
+ return
+
if cmd:
self.barscale.cmd = cmd
if not showDialog:
self.barscale.Show()
- self.MapWindow.UpdateMap()
return
# Decoration overlay control dialog
- if self.dialogs['barscale']:
- if self.dialogs['barscale'].IsShown():
- self.dialogs['barscale'].SetFocus()
+ if self.barscale.dialog:
+ if self.barscale.dialog.IsShown():
+ self.barscale.dialog.SetFocus()
+ self.barscale.dialog.Raise()
else:
- self.dialogs['barscale'].Show()
+ self.barscale.dialog.Show()
else:
# If location is latlon, only display north arrow (scale won't work)
# proj = self.Map.projinfo['proj']
@@ -945,23 +965,17 @@
# barcmd = 'd.barscale'
# decoration overlay control dialog
- self.dialogs['barscale'] = \
- DecorationDialog(parent=self, title=_('Scale and North arrow'),
- giface=self._giface,
- overlayController=self.barscale,
- ddstyle=DECOR_DIALOG_BARSCALE,
- size=(350, 200),
- style=wx.DEFAULT_DIALOG_STYLE | wx.CENTRE)
+ GUI(parent=self, giface=self._giface, show=True,
+ modal=False).ParseCommand(self.barscale.cmd,
+ completed=(self.barscale.GetOptData, None, None))
- self.dialogs['barscale'].CentreOnParent()
- ### dialog cannot be show as modal - in the result d.barscale is not selectable
- ### self.dialogs['barscale'].ShowModal()
- self.dialogs['barscale'].Show()
self.MapWindow.mouse['use'] = 'pointer'
- def AddLegend(self, cmd = None, showDialog = True):
- """!Handler for legend map decoration menu selection.
- """
+ def AddLegend(self, cmd=None, showDialog=None):
+ """!Handler for legend map decoration menu selection."""
+ if self.legend.IsShown() and showDialog is None:
+ self.legend.Hide()
+ return
if cmd:
self.legend.cmd = cmd
else:
@@ -971,32 +985,56 @@
self.legend.cmd.append('map=%s' % layer.maplayer.name)
break
- if not showDialog:
+ if not showDialog and self.legend.CmdIsValid():
self.legend.Show()
- self.MapWindow.UpdateMap()
return
# Decoration overlay control dialog
- if self.dialogs['legend']:
- if self.dialogs['legend'].IsShown():
- self.dialogs['legend'].SetFocus()
+ if self.legend.dialog:
+ if self.legend.dialog.IsShown():
+ self.legend.dialog.SetFocus()
+ self.legend.dialog.Raise()
else:
- self.dialogs['legend'].Show()
+ self.legend.dialog.Show()
else:
- self.dialogs['legend'] = \
- DecorationDialog(parent=self, title=_("Legend"),
- overlayController=self.legend,
- giface=self._giface,
- ddstyle=DECOR_DIALOG_LEGEND,
- size=(350, 200),
- style=wx.DEFAULT_DIALOG_STYLE | wx.CENTRE)
+ GUI(parent=self, giface=self._giface, show=True,
+ modal=False).ParseCommand(self.legend.cmd,
+ completed=(self.legend.GetOptData, None, None))
- self.dialogs['legend'].CentreOnParent()
- ### dialog cannot be show as modal - in the result d.legend is not selectable
- ### self.dialogs['legend'].ShowModal()
- self.dialogs['legend'].Show()
self.MapWindow.mouse['use'] = 'pointer'
-
+
+ def AddArrow(self, cmd=None, showDialog=None):
+ """!Handler for north arrow menu selection."""
+ if self.IsPaneShown('3d'):
+ # here was opening of appearance page of nviz notebook
+ # but now moved to MapWindow3D where are other problematic nviz calls
+ self.MapWindow3D.SetDrawArrow((70, 70))
+ return
+
+ if self.arrow.IsShown() and showDialog is None:
+ self.arrow.Hide()
+ return
+ if cmd:
+ self.arrow.cmd = cmd
+
+ if not showDialog:
+ self.arrow.Show()
+ return
+
+ # Decoration overlay control dialog
+ if self.arrow.dialog:
+ if self.arrow.dialog.IsShown():
+ self.arrow.dialog.SetFocus()
+ self.arrow.dialog.Raise()
+ else:
+ self.arrow.dialog.Show()
+ else:
+ GUI(parent=self, giface=self._giface, show=True,
+ modal=False).ParseCommand(self.arrow.cmd,
+ completed=(self.arrow.GetOptData, None, None))
+
+ self.MapWindow.mouse['use'] = 'pointer'
+
def OnAddText(self, event):
"""!Handler for text decoration menu selection.
"""
@@ -1047,13 +1085,6 @@
self.MapWindow2D.UpdateMap(render = False, renderVector = False)
self.MapWindow.mouse['use'] = 'pointer'
-
- def OnAddArrow(self, event):
- """!Handler for north arrow menu selection.
- """
- # here was opening of appearance page of nviz notebook
- # but now moved to MapWindow3D where are other problematic nviz calls
- self.MapWindow3D.SetDrawArrow((70, 70))
def GetOptData(self, dcmd, type, params, propwin):
"""!Callback method for decoration overlay command generated by
Modified: grass/trunk/gui/wxpython/mapdisp/toolbars.py
===================================================================
--- grass/trunk/gui/wxpython/mapdisp/toolbars.py 2013-09-18 15:58:49 UTC (rev 57737)
+++ grass/trunk/gui/wxpython/mapdisp/toolbars.py 2013-09-18 16:44:27 UTC (rev 57738)
@@ -29,11 +29,11 @@
label = _('Query raster/vector map(s)'),
desc = _('Query selected raster/vector map(s)')),
'addBarscale': MetaIcon(img = 'scalebar-add',
- label = _('Add scalebar and north arrow')),
+ label = _('Show/hide scale bar')),
'addLegend' : MetaIcon(img = 'legend-add',
- label = _('Add legend')),
+ label = _('Show/hide legend')),
'addNorthArrow': MetaIcon(img = 'north-arrow-add',
- label = _('North Arrow')),
+ label = _('Show/hide north arrow')),
'analyze' : MetaIcon(img = 'layer-raster-analyze',
label = _('Analyze map'),
desc = _('Measuring, profiling, histogramming, ...')),
@@ -244,14 +244,11 @@
def OnDecoration(self, event):
"""!Decorations overlay menu
"""
- if self.parent.IsPaneShown('3d'):
- self._onMenu(((MapIcons["addNorthArrow"], self.parent.OnAddArrow),
- (MapIcons["addLegend"], lambda evt: self.parent.AddLegend()),
- (MapIcons["addText"], self.parent.OnAddText)))
- else:
- self._onMenu(((MapIcons["addBarscale"], lambda evt: self.parent.AddBarscale()),
- (MapIcons["addLegend"], lambda evt: self.parent.AddLegend()),
- (MapIcons["addText"], self.parent.OnAddText)))
+ self._onMenu(((MapIcons["addLegend"], lambda evt: self.parent.AddLegend()),
+ (MapIcons["addBarscale"], lambda evt: self.parent.AddBarscale()),
+ (MapIcons["addNorthArrow"], lambda evt: self.parent.AddArrow()),
+ (MapIcons["addText"], self.parent.OnAddText)))
+
def ExitToolbars(self):
if self.parent.GetToolbar('vdigit'):
Modified: grass/trunk/gui/wxpython/mapwin/base.py
===================================================================
--- grass/trunk/gui/wxpython/mapwin/base.py 2013-09-18 15:58:49 UTC (rev 57737)
+++ grass/trunk/gui/wxpython/mapwin/base.py 2013-09-18 16:44:27 UTC (rev 57738)
@@ -115,6 +115,8 @@
self.mouseHandlerUnregistered = Signal('MapWindow.mouseHandlerUnregistered')
# emitted after double click in pointer mode on legend, text, scalebar
self.overlayActivated = Signal('MapWindow.overlayActivated')
+ # emitted when overlay should be hidden
+ self.overlayHidden = Signal('MapWindow.overlayHidden')
# mouse attributes -- position on the screen, begin and end of
# dragging, and type of drawing
Modified: grass/trunk/gui/wxpython/mapwin/buffered.py
===================================================================
--- grass/trunk/gui/wxpython/mapwin/buffered.py 2013-09-18 15:58:49 UTC (rev 57737)
+++ grass/trunk/gui/wxpython/mapwin/buffered.py 2013-09-18 16:44:27 UTC (rev 57738)
@@ -134,6 +134,7 @@
self.img = None # wx.Image object (self.mapfile)
# decoration overlays
self.overlays = overlays
+ self._overlayNames = {0: _("legend"), 1: _("scale bar"), 2: _("north arrow")}
# images and their PseudoDC ID's for painting and dragging
self.imagedict = {}
self.select = {} # selecting/unselecting decorations for dragging
@@ -192,14 +193,30 @@
event.Skip()
return
+ # generate popup-menu
+ menu = wx.Menu()
+
if not hasattr(self, "popupCopyCoordinates"):
self.popupCopyCoordinates = wx.NewId()
self.Bind(wx.EVT_MENU, self.OnCopyCoordinates, id = self.popupCopyCoordinates)
-
- # generate popup-menu
- menu = wx.Menu()
menu.Append(self.popupCopyCoordinates, _("Copy coordinates to clipboard"))
+ pos = self.ScreenToClient(event.GetPosition())
+ idlist = self.pdc.FindObjects(pos[0], pos[1], self.hitradius)
+ if idlist and idlist[0] in (0, 1, 2): # legend, scale bar, north arrow
+ self._hide = wx.NewId()
+ self.Bind(wx.EVT_MENU,
+ lambda evt: self.overlayHidden.emit(overlayId=idlist[0]),
+ id=self._hide)
+ menu.Append(self._hide,
+ _("Hide {overlay}").format(overlay=self._overlayNames[idlist[0]]))
+
+ if idlist[0] == 0:
+ self._resizeLegend = wx.NewId()
+ self.Bind(wx.EVT_MENU,
+ lambda evt: self.overlays[idlist[0]].StartResizing(),
+ id=self._resizeLegend)
+ menu.Append(self._resizeLegend, _("Resize legend"))
self.PopupMenu(menu)
menu.Destroy()
@@ -581,7 +598,7 @@
for overlay in self.Map.GetListOfLayers(ltype = "overlay", active = True):
if overlay.mapfile is not None \
and os.path.isfile(overlay.mapfile) and os.path.getsize(overlay.mapfile):
- img = wx.Image(overlay.mapfile, wx.BITMAP_TYPE_ANY)
+ img = utils.autoCropImageFromFile(overlay.mapfile)
for key in self.imagedict.keys():
if self.imagedict[key]['id'] == overlay.id:
Modified: grass/trunk/gui/wxpython/mapwin/decorations.py
===================================================================
--- grass/trunk/gui/wxpython/mapwin/decorations.py 2013-09-18 15:58:49 UTC (rev 57737)
+++ grass/trunk/gui/wxpython/mapwin/decorations.py 2013-09-18 16:44:27 UTC (rev 57738)
@@ -6,8 +6,8 @@
Classes:
- decorations::OverlayController
- decorations::BarscaleController
+ - decorations::ArrowController
- decorations::LegendController
- - decorations::DecorationDialog
- decorations::TextLayerDialog
(C) 2006-2013 by the GRASS Development Team
@@ -19,27 +19,31 @@
"""
import wx
-from core.utils import GetLayerNameFromCmd, _
-from gui_core.forms import GUI
+from core.utils import _
-from grass.pydispatch.errors import DispatcherKeyError
+from grass.pydispatch.signal import Signal
class OverlayController(object):
"""!Base class for decorations (barscale, legend) controller."""
- def __init__(self, renderer):
+ def __init__(self, renderer, giface):
+ self._giface = giface
self._renderer = renderer
self._overlay = None
- self._coords = [0, 0]
+ self._coords = None
self._pdcType = 'image'
self._propwin = None
self._defaultAt = ''
self._cmd = None # to be set by user
self._name = None # to be defined by subclass
self._id = None # to be defined by subclass
+ self._dialog = None
+ # signals that overlay or its visibility changed
+ self.overlayChanged = Signal('OverlayController::overlayChanged')
+
def SetCmd(self, cmd):
hasAt = False
for i in cmd:
@@ -59,6 +63,9 @@
self._coords = list(coords)
def GetCoords(self):
+ if self._coords is None: # initial position
+ x, y = self.GetPlacement((self._renderer.width, self._renderer.height))
+ self._coords = [x, y]
return self._coords
coords = property(fset=SetCoords, fget=GetCoords)
@@ -91,6 +98,14 @@
layer = property(fget=GetLayer)
+ def GetDialog(self):
+ return self._dialog
+
+ def SetDialog(self, win):
+ self._dialog = win
+
+ dialog = property(fget=GetDialog, fset=SetDialog)
+
def IsShown(self):
if self._overlay and self._overlay.IsActive():
return True
@@ -106,10 +121,29 @@
else:
self.Hide()
+ self.overlayChanged.emit()
+
def Hide(self):
if self._overlay:
self._overlay.SetActive(False)
+ self.overlayChanged.emit()
+ def GetOptData(self, dcmd, layer, params, propwin):
+ """!Called after options are set through module dialog.
+
+ @param dcmd resulting command
+ @param layer not used
+ @param params module parameters (not used)
+ @param propwin dialog window
+ """
+ if not dcmd:
+ return
+
+ self._cmd = dcmd
+ self._dialog = propwin
+
+ self.Show()
+
def _add(self):
self._overlay = self._renderer.AddOverlay(id=self._id, ltype=self._name,
command=self.cmd, active=False,
@@ -120,27 +154,74 @@
self._renderer.ChangeOverlay(id=self._id, command=self._cmd,
render=False)
+ def CmdIsValid(self):
+ """!If command is valid"""
+ return True
+ def GetPlacement(self, screensize):
+ """!Get coordinates where to place overlay in a reasonable way
+
+ @param screensize sreen size
+ """
+ for param in self._cmd:
+ if not param.startswith('at'):
+ continue
+ x, y = [float(number) for number in param.split('=')[1].split(',')]
+ x = int((x / 100.) * screensize[0])
+ y = int((1 - y / 100.) * screensize[1])
+
+ return x, y
+
+
class BarscaleController(OverlayController):
- def __init__(self, renderer):
- OverlayController.__init__(self, renderer)
- self._id = 0
+ def __init__(self, renderer, giface):
+ OverlayController.__init__(self, renderer, giface)
+ self._id = 1
self._name = 'barscale'
- self._defaultAt = 'at=0,95'
+ # different from default because the reference point is not in the middle
+ self._defaultAt = 'at=0,98'
self._cmd = ['d.barscale', self._defaultAt]
+class ArrowController(OverlayController):
+
+ def __init__(self, renderer, giface):
+ OverlayController.__init__(self, renderer, giface)
+ self._id = 2
+ self._name = 'arrow'
+ # different from default because the reference point is not in the middle
+ self._defaultAt = 'at=85.0,25.0'
+ self._cmd = ['d.northarrow', self._defaultAt]
+
+
class LegendController(OverlayController):
- def __init__(self, renderer):
- OverlayController.__init__(self, renderer)
- self._id = 1
+ def __init__(self, renderer, giface):
+ OverlayController.__init__(self, renderer, giface)
+ self._id = 0
self._name = 'legend'
# TODO: synchronize with d.legend?
self._defaultAt = 'at=5,50,2,5'
self._cmd = ['d.legend', self._defaultAt]
+ def GetPlacement(self, screensize):
+ for param in self._cmd:
+ if not param.startswith('at'):
+ continue
+ b, t, l, r = [float(number) for number in param.split('=')[1].split(',')] # pylint: disable-msg=W0612
+ x = int((l / 100.) * screensize[0])
+ y = int((1 - t / 100.) * screensize[1])
+
+ return x, y
+
+ def CmdIsValid(self):
+ for param in self._cmd:
+ param = param.split('=')
+ if param[0] == 'map' and len(param) == 2:
+ return True
+ return False
+
def ResizeLegend(self, begin, end, screenSize):
"""!Resize legend according to given bbox coordinates."""
w = abs(begin[0] - end[0])
@@ -165,213 +246,29 @@
self._cmd[i] = atStr
break
- self._coords = [0, 0]
+ self._coords = None
self.Show()
-
-DECOR_DIALOG_LEGEND = 0
-DECOR_DIALOG_BARSCALE = 1
-
-
-class DecorationDialog(wx.Dialog):
-
- """!Controls setting options and displaying/hiding map overlay
- decorations
- """
-
- def __init__(self, parent, title, giface, overlayController,
- ddstyle, **kwargs):
-
- wx.Dialog.__init__(self, parent, wx.ID_ANY, title, **kwargs)
-
- self.parent = parent # MapFrame
- self._overlay = overlayController
- self._ddstyle = ddstyle
- self._giface = giface
-
- sizer = wx.BoxSizer(wx.VERTICAL)
-
- box = wx.BoxSizer(wx.HORIZONTAL)
- self.chkbox = wx.CheckBox(parent=self, id=wx.ID_ANY)
- self.chkbox.SetValue(True)
-
- if self._ddstyle == DECOR_DIALOG_LEGEND:
- self.chkbox.SetLabel("Show legend")
- else:
- self.chkbox.SetLabel("Show scale and North arrow")
-
- box.Add(item=self.chkbox, proportion=0,
- flag=wx.ALIGN_CENTRE | wx.ALL, border=5)
- sizer.Add(item=box, proportion=0,
- flag=wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
-
- box = wx.BoxSizer(wx.HORIZONTAL)
- optnbtn = wx.Button(parent=self, id=wx.ID_ANY, label=_("Set options"))
- box.Add(item=optnbtn, proportion=0, flag=wx.ALIGN_CENTRE | wx.ALL, border=5)
- sizer.Add(item=box, proportion=0,
- flag=wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
- if self._ddstyle == DECOR_DIALOG_LEGEND:
- box = wx.BoxSizer(wx.HORIZONTAL)
- self.resizeBtn = wx.ToggleButton(
- parent=self, id=wx.ID_ANY, label=_("Set size and position"))
- self.resizeBtn.SetToolTipString(_("Click and drag on the map display to set legend "
- "size and position and then press OK"))
- self.resizeBtn.Disable()
- toolSwitcher = self._giface.GetMapDisplay().GetToolSwitcher()
- toolSwitcher.AddCustomToolToGroup(group='mouseUse', btnId=self.resizeBtn.GetId(),
- toggleHandler=self.resizeBtn.SetValue)
- toolSwitcher.toggleToolChanged.connect(self._toolChanged)
- self.resizeBtn.Bind(wx.EVT_TOGGLEBUTTON, lambda evt: toolSwitcher.ToolChanged(evt.GetId()))
-
- box.Add(item=self.resizeBtn, proportion=0,
- flag=wx.ALIGN_CENTRE | wx.ALL, border=5)
- sizer.Add(item=box, proportion=0,
- flag=wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
-
- box = wx.BoxSizer(wx.HORIZONTAL)
- if self._ddstyle == DECOR_DIALOG_LEGEND:
- labelText = _("Drag legend object with mouse in pointer mode to position.\n"
- "Double-click to change options.\n"
- "Define raster map name for legend in properties dialog.")
- else:
- labelText = _("Drag scale object with mouse in pointer mode to position.\n"
- "Double-click to change options.")
-
- label = wx.StaticText(parent=self, id=wx.ID_ANY,
- label=labelText)
-
- box.Add(item=label, proportion=0,
- flag=wx.ALIGN_CENTRE | wx.ALL, border=5)
- sizer.Add(item=box, proportion=0,
- flag=wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
-
- line = wx.StaticLine(
- parent=self, id=wx.ID_ANY, size=(20, -1), style = wx.LI_HORIZONTAL)
- sizer.Add(item=line, proportion=0,
- flag=wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
-
- # buttons
- btnsizer = wx.StdDialogButtonSizer()
-
- self.btnOK = wx.Button(parent=self, id=wx.ID_OK)
- self.btnOK.SetDefault()
- self.btnOK.Enable(self._ddstyle != DECOR_DIALOG_LEGEND)
- btnsizer.AddButton(self.btnOK)
-
- btnCancel = wx.Button(parent=self, id=wx.ID_CANCEL)
- btnsizer.AddButton(btnCancel)
- btnsizer.Realize()
-
- sizer.Add(item=btnsizer, proportion=0,
- flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
-
- #
- # bindings
- #
- optnbtn.Bind(wx.EVT_BUTTON, self.OnOptions)
- btnCancel.Bind(wx.EVT_BUTTON, lambda evt: self.CloseDialog())
- self.btnOK.Bind(wx.EVT_BUTTON, self.OnOK)
-
- self.SetSizer(sizer)
- sizer.Fit(self)
-
- mapName, found = GetLayerNameFromCmd(self._overlay.cmd)
- if found:
- # enable 'OK' and 'Resize' button
- self.btnOK.Enable()
-
- # set title
- self.SetTitle(_('Legend of raster map <%s>') %
- mapName)
-
- def OnOptions(self, event):
- """!Sets option for decoration map overlays
- """
- if self._overlay.propwin is None:
- # build properties dialog
- GUI(parent=self.parent).ParseCommand(cmd=self._overlay.cmd,
- completed=(self.GetOptData, self._overlay.name, ''))
-
- else:
- if self._overlay.propwin.IsShown():
- self._overlay.propwin.SetFocus()
- else:
- self._overlay.propwin.Show()
-
- def _toolChanged(self, id):
+ def StartResizing(self):
"""!Tool in toolbar or button itself were pressed"""
- if id == self.resizeBtn.GetId():
- if self.resizeBtn.GetValue():
- # prepare for resizing
- window = self._giface.GetMapWindow()
- window.SetNamedCursor('cross')
- window.mouse['use'] = None
- window.mouse['box'] = 'box'
- window.pen = wx.Pen(colour='Black', width=2, style=wx.SHORT_DASH)
- window.mouseLeftUp.connect(self._resizeLegend)
- else:
- # stop resizing mode
- self.DisconnectResizing()
- self._giface.GetMapDisplay().GetMapToolbar().SelectDefault()
- else:
- # any other tool was pressed -> stop resizing mode
- self.DisconnectResizing()
+ # prepare for resizing
+ window = self._giface.GetMapWindow()
+ window.SetNamedCursor('cross')
+ window.mouse['use'] = None
+ window.mouse['box'] = 'box'
+ window.pen = wx.Pen(colour='Black', width=2, style=wx.SHORT_DASH)
+ window.mouseLeftUp.connect(self._finishResizing)
- def DisconnectResizing(self):
- if not self.parent.IsPaneShown('3d'):
- try:
- self._giface.GetMapWindow().mouseLeftUp.disconnect(self._resizeLegend)
- except DispatcherKeyError:
- pass
-
- def _resizeLegend(self, x, y):
- """!Update legend after drawing new legend size (moved from BufferedWindow)"""
- self._giface.GetMapDisplay().GetMapToolbar().SelectDefault()
- self.DisconnectResizing()
- # resize legend
+ def _finishResizing(self):
window = self._giface.GetMapWindow()
+ window.mouseLeftUp.disconnect(self._finishResizing)
screenSize = window.GetClientSizeTuple()
- self._overlay.ResizeLegend(window.mouse["begin"], window.mouse["end"], screenSize)
+ self.ResizeLegend(window.mouse["begin"], window.mouse["end"], screenSize)
+ self._giface.GetMapDisplay().GetMapToolbar().SelectDefault()
# redraw
- self._giface.updateMap.emit()
+ self.overlayChanged.emit()
- def CloseDialog(self):
- """!Hide dialog"""
- if self._ddstyle == DECOR_DIALOG_LEGEND and self.resizeBtn.GetValue():
- self.DisconnectResizing()
- self.Hide()
-
- def OnOK(self, event):
- """!Button 'OK' pressed"""
- # enable or disable overlay
- self._overlay.Show(self.chkbox.IsChecked())
-
- # update map
- if self.parent.IsPaneShown('3d'):
- self.parent.MapWindow.UpdateOverlays()
-
- self._giface.updateMap.emit()
-
- # hide dialog
- self.CloseDialog()
-
- def GetOptData(self, dcmd, layer, params, propwin):
- """!Process decoration layer data"""
- if dcmd:
- self._overlay.cmd = dcmd
- self._overlay.propwin = propwin
- if params:
- self.btnOK.Enable()
- if self._ddstyle == DECOR_DIALOG_LEGEND and not self.parent.IsPaneShown('3d'):
- self.resizeBtn.Enable()
-
- def Show(self, show=True):
- if show and self._ddstyle == DECOR_DIALOG_LEGEND:
- self.resizeBtn.Enable(not self.parent.IsPaneShown('3d'))
- wx.Dialog.Show(self, show)
-
-
class TextLayerDialog(wx.Dialog):
"""
@@ -440,7 +337,7 @@
flag=wx.ALIGN_CENTER_VERTICAL,
pos=(2, 0))
self.rotation = wx.SpinCtrl(parent=self, id=wx.ID_ANY, value="", pos=(30, 50),
- size = (75, -1), style = wx.SP_ARROW_KEYS)
+ size=(75, -1), style=wx.SP_ARROW_KEYS)
self.rotation.SetRange(-360, 360)
self.rotation.SetValue(int(self.currRot))
box.Add(item=self.rotation,
@@ -467,7 +364,7 @@
flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER | wx.ALL, border=5)
line = wx.StaticLine(parent=self, id=wx.ID_ANY,
- size=(20, -1), style = wx.LI_HORIZONTAL)
+ size=(20, -1), style=wx.LI_HORIZONTAL)
self.sizer.Add(item=line, proportion=0,
flag=wx.EXPAND | wx.ALIGN_CENTRE | wx.ALL, border=5)
Modified: grass/trunk/gui/wxpython/nviz/mapwindow.py
===================================================================
--- grass/trunk/gui/wxpython/nviz/mapwindow.py 2013-09-18 15:58:49 UTC (rev 57737)
+++ grass/trunk/gui/wxpython/nviz/mapwindow.py 2013-09-18 16:44:27 UTC (rev 57738)
@@ -443,8 +443,8 @@
def GetLegendRect(self):
"""!Estimates legend size for dragging"""
size = None
- if 1 in self.overlays:
- for param in self.overlays[1].cmd[1:]:
+ if 0 in self.overlays:
+ for param in self.overlays[0].cmd[1:]:
if param.startswith("at="):
size = map(int, param.split("=")[-1].split(','))
break
@@ -494,7 +494,7 @@
Updates self.imagelist"""
self.Map.ChangeMapSize(self.GetClientSize())
self.Map.RenderOverlays(force = True)
-
+
# delete textures
for texture in self.imagelist:
# inactive overlays, remove text labels
@@ -509,7 +509,7 @@
# update images (only legend so far)
for oid, overlay in self.overlays.iteritems():
- if not overlay.IsShown() or oid == 0: # 0 for barscale
+ if not overlay.IsShown() or oid in (1, 2): # 0 for barscale
continue
if oid not in [t.GetId() for t in self.imagelist]: # new
self.CreateTexture(overlay = overlay.layer)
@@ -519,10 +519,7 @@
if not t.Corresponds(overlay):
self.imagelist.remove(t)
t = self.CreateTexture(overlay = overlay.layer)
- # always set coordinates, needed for synchr. 2D and 3D modes
- t.SetCoords(overlay.coords)
-
# update text labels
for textId in self.textdict.keys():
if textId not in [t.GetId() for t in self.imagelist]:# new
@@ -536,6 +533,7 @@
t = self.CreateTexture(textId = textId)
# always set coordinates, needed for synchr. 2D and 3D modes
t.SetCoords(self.textdict[textId]['coords'])
+ self.Refresh()
def CreateTexture(self, overlay = None, textId = None):
"""!Create texture from overlay image or from textdict"""
@@ -543,7 +541,7 @@
texture = wxnviz.ImageTexture(filepath = overlay.mapfile, overlayId = overlay.id,
coords = list(self.overlays[overlay.id].coords),
cmd = overlay.GetCmd())
- if overlay.id == 1: # legend
+ if overlay.id == 0: # legend
texture.SetBounds(self.GetLegendRect())
else: # text
coords, bbox, relCoords = self.TextBounds(self.textdict[textId])
@@ -741,8 +739,7 @@
if self.mouse['use'] == 'pointer':
# get decoration or text id
self.dragid = self.FindObjects(self.mouse['tmp'][0], self.mouse['tmp'][1],
- self.hitradius)
-
+ self.hitradius)
if self.mouse['use'] == 'fly':
if not self.timerFly.IsRunning():
self.timerFly.Start(self.fly['interval'])
@@ -753,7 +750,7 @@
def OnDragging(self, event):
if self.mouse['use'] == 'pointer':
- if self.dragid > 0:
+ if self.dragid >= 0:
self.DragItem(self.dragid, event.GetPositionTuple())
if self.mouse['use'] == 'rotate':
@@ -844,7 +841,7 @@
elif self.mouse['use'] == 'pointer':
- if self.dragid > 0:
+ if self.dragid >= 0:
dx = self.mouse['end'][0] - self.mouse['begin'][0]
dy = self.mouse['end'][1] - self.mouse['begin'][1]
if self.dragid < 99:
@@ -964,7 +961,8 @@
def DragItem(self, id, coords):
"""!Drag an overlay decoration item
"""
- if not id: return
+ if id is None:
+ return
Debug.msg (5, "GLWindow.DragItem(): id=%d" % id)
x, y = self.mouse['tmp']
dx = coords[0] - x
@@ -1268,6 +1266,7 @@
self.decoration['scalebar'][-1]['position']['x'] = pos[0]
self.decoration['scalebar'][-1]['position']['y'] = pos[1]
self.Refresh(False)
+ self.lmgr.nviz.SetPage('decoration')
def IsLoaded(self, item):
"""!Check if layer (item) is already loaded
Modified: grass/trunk/gui/wxpython/nviz/wxnviz.py
===================================================================
--- grass/trunk/gui/wxpython/nviz/wxnviz.py 2013-09-18 15:58:49 UTC (rev 57737)
+++ grass/trunk/gui/wxpython/nviz/wxnviz.py 2013-09-18 16:44:27 UTC (rev 57738)
@@ -1998,7 +1998,7 @@
self.width = self.image.GetWidth()
self.height = self.image.GetHeight()
self.id = overlayId
- self.coords = list(coords)
+ self.coords = [0, 0]
self.bounds = wx.Rect()
self.active = True
More information about the grass-commit
mailing list