[GRASS-SVN] r47307 - grass/trunk/gui/wxpython/gui_modules
svn_grass at osgeo.org
svn_grass at osgeo.org
Fri Jul 29 10:16:22 EDT 2011
Author: annakrat
Date: 2011-07-29 07:16:22 -0700 (Fri, 29 Jul 2011)
New Revision: 47307
Modified:
grass/trunk/gui/wxpython/gui_modules/nviz_mapdisp.py
Log:
wxNviz: draw overlays with wx.Overlay
Modified: grass/trunk/gui/wxpython/gui_modules/nviz_mapdisp.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/nviz_mapdisp.py 2011-07-29 11:43:29 UTC (rev 47306)
+++ grass/trunk/gui/wxpython/gui_modules/nviz_mapdisp.py 2011-07-29 14:16:22 UTC (rev 47307)
@@ -86,7 +86,8 @@
self.render = { 'quick' : False,
# do not render vector lines in quick mode
'vlines' : False,
- 'vpoints' : False }
+ 'vpoints' : False,
+ 'overlays': False }
self.mouse = {
'use': 'pointer'
}
@@ -105,11 +106,11 @@
# overlays
self.overlays = {}
self.imagedict = {}
- self.shapes = []
- self.dragShape = None
- self.dragImage = None
+ self.overlay = wx.Overlay()
+ self.pdc = wx.PseudoDC()
self.textdict = {}
self.dragid = None
+ self.hitradius = 5
if self.lmgr:
self.log = self.lmgr.goutput
@@ -119,7 +120,7 @@
self.log = logmsg = sys.stdout
logerr = sys.stderr
- # create nviz instanve - use display region instead of computational
+ # create nviz instance - use display region instead of computational
os.environ['GRASS_REGION'] = self.Map.SetRegion()
self.nvizThread = NvizThread(logerr,
@@ -155,6 +156,7 @@
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseAction)
self.Bind(wx.EVT_MOTION, self.OnMotion)
+ self.Bind(wx.EVT_IDLE, self.OnIdle)
self.Bind(EVT_UPDATE_PROP, self.UpdateMapObjProperties)
self.Bind(EVT_UPDATE_VIEW, self.UpdateView)
@@ -211,13 +213,19 @@
size.height)
self.size = size
event.Skip()
-
+
+ def OnIdle(self, event):
+ if self.render['overlays']:
+ self.DrawOverlays()
+ self.render['overlays'] = False
+
def OnPaint(self, event):
Debug.msg(1, "GLCanvas.OnPaint()")
+ self.render['overlays'] = True
dc = wx.PaintDC(self)
self.DoPaint()
- self.DrawShapes(dc)
+
def DoPaint(self):
self.SetCurrent()
@@ -256,54 +264,67 @@
self.UpdateMap()
- def UpdateOverlays(self):
- if self.img is None:
- self.Map.ChangeMapSize(self.GetClientSize())
- self.Map.RenderOverlays(force = True)
- else:
- self.Map.RenderOverlays(force = False)
- self.shapes = []
+ def DrawOverlays(self):
+ """!Draw overlays with wx.Overlay"""
+ dc = wx.ClientDC(self)
+ odc = wx.DCOverlay(self.overlay, dc)
+ self.pdc.Clear()
+ self.pdc.RemoveAll()
for img in self.GetOverlay():
# draw any active and defined overlays
if self.imagedict[img]['layer'].IsActive():
id = self.imagedict[img]['id']
- if id == 0: # barscale
- continue
- coords = self.overlays[id]['coords']
- bitmap = wx.BitmapFromImage(img)
- self.shapes.append(DragShape(bitmap, id))
- self.shapes[-1].pos = coords[:2]
-
+ self.DrawImage(img = img, drawid = id, coords = self.overlays[id]['coords'])
+
for textId in self.textdict.keys():
- text = self.textdict[textId]['text']
- color = self.textdict[textId]['color']
- bgcolor = self.view['background']['color']
- font = self.textdict[textId]['font']
- rot = self.textdict[textId]['rotation']
- coords, bbox, relCoords = self.TextBounds(self.textdict[textId])
# create a bitmap the same size as our text
- bmp = wx.EmptyBitmap(bbox[2], bbox[3])
-
- # 'draw' the text onto the bitmap
- dc = wx.MemoryDC()
- dc.SelectObject(bmp)
- dc.SetBackground(wx.Brush(bgcolor, wx.SOLID))
- dc.Clear()
- dc.SetTextForeground(color)
- dc.SetFont(font)
- if rot == 0:
- dc.DrawText(text, 0, 0)
- else:
- dc.DrawRotatedText(text, relCoords[0], relCoords[1], rot)
- # setbackgroundMode(wx.TRANSPARENT) doesn't work
- dc.SelectObject(wx.NullBitmap)
- mask = wx.Mask(bmp, bgcolor)
- bmp.SetMask(mask)
- shape = DragShape(bmp, textId)
- shape.pos = bbox[:2]
- self.shapes.append(shape)
+ self.DrawText(drawid = textId)
+
+ self.pdc.DrawToDC(dc)
+ del odc
+ self.overlay.Reset()
- self.Refresh(False)
+ def DrawImage(self, img, drawid, coords):
+ """!Draw overlay image"""
+ bitmap = wx.BitmapFromImage(img)
+ w,h = bitmap.GetSize()
+
+ self.pdc.BeginDrawing()
+ self.pdc.SetBackground(wx.TRANSPARENT_BRUSH)
+ self.pdc.RemoveId(drawid)
+ self.pdc.SetId(drawid)
+ self.pdc.DrawBitmap(bitmap, coords[0], coords[1], True)
+ self.pdc.SetIdBounds(drawid, wx.Rect(coords[0],coords[1], w, h))
+ self.pdc.EndDrawing()
+
+ def DrawText(self, drawid):
+ """!Draw overlay text"""
+ self.pdc.BeginDrawing()
+ self.pdc.SetBackground(wx.TRANSPARENT_BRUSH)
+ self.pdc.RemoveId(drawid)
+ self.pdc.SetId(drawid)
+ self.pdc.SetFont(self.textdict[drawid]['font'])
+ self.pdc.SetTextForeground(self.textdict[drawid]['color'])
+ if self.textdict[drawid]['rotation'] == 0:
+ self.pdc.DrawText(self.textdict[drawid]['text'], self.textdict[drawid]['coords'][0],
+ self.textdict[drawid]['coords'][1])
+ else:
+ self.pdc.DrawRotatedText(self.textdict[drawid]['text'], self.textdict[drawid]['coords'][0],
+ self.textdict[drawid]['coords'][1],
+ self.textdict[drawid]['rotation'])
+ self.pdc.SetIdBounds(drawid, self.textdict[drawid]['bbox'])
+ self.pdc.EndDrawing()
+
+ def UpdateOverlays(self):
+ self.Map.ChangeMapSize(self.GetClientSize())
+ self.Map.RenderOverlays(force = True)
+
+ for textId in self.textdict.keys():
+ coords, bbox, relCoords = self.TextBounds(self.textdict[textId])
+ self.textdict[textId]['coords'] = coords
+ self.textdict[textId]['bbox'] = bbox
+ # rerender OnIdle
+ self.render['overlays'] = True
def OnMouseAction(self, event):
"""!Handle mouse events"""
@@ -362,6 +383,7 @@
def OnLeftDown(self, event):
"""!On left mouse down"""
+ self.mouse['begin'] = event.GetPositionTuple()
if self.mouse['use'] == "lookHere":
pos = event.GetPosition()
size = self.GetClientSize()
@@ -391,11 +413,13 @@
self.SetDrawArrow((pos[0], size[1] - pos[1]))
if self.mouse['use'] == 'pointer':
- shape = self.FindShape(event.GetPosition())
- if shape:
- self.dragShape = shape
- self.dragStartPos = event.GetPosition()
- self.deleteOld = True
+ # get decoration or text id
+ self.dragid = None
+ self.mouse['tmp'] = self.mouse['begin']
+ idlist = self.pdc.FindObjects(self.mouse['tmp'][0], self.mouse['tmp'][1],
+ self.hitradius)
+ if idlist != []:
+ self.dragid = idlist[0] #drag whatever is on top
event.Skip()
@@ -410,42 +434,7 @@
self.cplanes[idx]['position']['y'] = y
if self.mouse['use'] == 'pointer':
- if not self.dragShape:
- event.Skip()
- return
- if self.dragShape and not self.dragImage:
- # only start the drag after having moved a couple pixels
- tolerance = 2
- pt = event.GetPosition()
- dx = abs(pt.x - self.dragStartPos.x)
- dy = abs(pt.y - self.dragStartPos.y)
- if dx <= tolerance and dy <= tolerance:
- return
- elif self.deleteOld:
- # refresh the area of the window where the shape was so it
- # will get erased.
- # need to be redrawn now ?
- self.dragShape.shown = False
- self.RefreshRect(self.dragShape.GetRect(), False)
- self.Update()
- self.deleteOld = False
- return
- else:
- if self.dragShape.text:
- self.dragImage = wx.DragString(self.dragShape.text,
- wx.StockCursor(wx.CURSOR_HAND))
- else:
- self.dragImage = wx.DragImage(self.dragShape.bmp,
- wx.StockCursor(wx.CURSOR_HAND))
- hotspot = self.dragStartPos - self.dragShape.pos
- self.dragImage.BeginDrag(hotspot, self)
- self.dragImage.Move(pt)
- self.dragImage.Show()
-
- elif self.dragShape and self.dragImage:
- # now move it and show it again if needed
- self.dragImage.Move(event.GetPosition())
- self.dragImage.Show()
+ self.DragItem(self.dragid, event)
event.Skip()
@@ -489,41 +478,57 @@
self.mouse['use'] = 'pointer'
self.SetCursor(self.cursors['default'])
elif self.mouse['use'] == 'pointer':
- if not self.dragImage or not self.dragShape:
- self.dragImage = None
- self.dragShape = None
- return
-
- # Hide the image, end dragging, and nuke out the drag image.
- self.dragImage.Hide()
- self.dragImage.EndDrag()
- self.dragImage = None
-
-
- # reposition and draw the shape
- self.dragShape.pos = (
- self.dragShape.pos[0] + event.GetPosition()[0] - self.dragStartPos[0],
- self.dragShape.pos[1] + event.GetPosition()[1] - self.dragStartPos[1]
- )
- if self.dragShape.id in self.overlays:
- self.overlays[self.dragShape.id]['coords'] = tuple(self.dragShape.GetRect())
- else: # text
- self.textdict[self.dragShape.id]['bbox'] = self.dragShape.GetRect()
- self.textdict[self.dragShape.id]['coords'][0] += event.GetPosition()[0] - self.dragStartPos[0]
- self.textdict[self.dragShape.id]['coords'][1] += event.GetPosition()[1] - self.dragStartPos[1]
- self.dragShape.shown = True
- self.RefreshRect(self.dragShape.GetRect())
- self.dragShape = None
- event.Skip()
+ if self.dragid < 99 and self.dragid in self.overlays:
+ self.overlays[self.dragid]['coords'] = self.pdc.GetIdBounds(self.dragid)
+ elif self.dragid > 100 and self.dragid in self.textdict:
+ self.textdict[self.dragid]['bbox'] = self.pdc.GetIdBounds(self.dragid)
+
+ self.dragid = None
+ self.Refresh(False)
def OnDClick(self, event):
- shape = self.FindShape(event.GetPosition())
- if shape.id == 1:
+ """!On mouse double click"""
+ if self.mouse['use'] != 'pointer': return
+ pos = event.GetPositionTuple()
+ idlist = self.pdc.FindObjects(pos[0], pos[1], self.hitradius)
+ if idlist == []:
+ return
+ self.dragid = idlist[0]
+
+ if self.dragid == 1:
self.parent.OnAddLegend(None)
- elif shape.id > 100:
- self.dragid = shape.id
+ elif self.dragid > 100:
self.parent.OnAddText(None)
-
+
+ def DragItem(self, id, event):
+ """!Drag an overlay decoration item
+ """
+ if not id: return
+ Debug.msg (5, "GLWindow.DragItem(): id=%d" % id)
+
+ x, y = self.mouse['tmp']
+ dx = event.GetX() - x
+ dy = event.GetY() - y
+ self.pdc.SetBackground(wx.TRANSPARENT_BRUSH)
+ self.pdc.TranslateId(id, dx, dy)
+
+ r2 = self.pdc.GetIdBounds(id)
+ if type(r2) is list:
+ r2 = wx.Rect(r[0], r[1], r[2], r[3])
+ if id > 100: # text
+ self.textdict[id]['bbox'] = r2
+ self.textdict[id]['coords'][0] += dx
+ self.textdict[id]['coords'][1] += dy
+ else:
+ self.overlays[id]['coords'] = r2
+
+ dc = wx.ClientDC(self)
+ odc = wx.DCOverlay(self.overlay, dc)
+ odc.Clear()
+ self.pdc.DrawToDC(dc)
+ del odc
+ self.mouse['tmp'] = (event.GetX(), event.GetY())
+
def OnQuerySurface(self, event):
"""!Query surface on given position"""
size = self.GetClientSizeTuple()
@@ -653,17 +658,6 @@
self._display.EraseMap()
self.SwapBuffers()
- def DrawShapes(self, dc):
- for shape in self.shapes:
- if shape.shown:
- shape.Draw(dc)
-
- def FindShape(self, pt):
- for shape in self.shapes:
- if shape.HitTest(pt):
- return shape
- return None
-
def SetDrawArrow(self, pos):
if self._display.SetArrow(pos[0], pos[1],
@@ -1923,32 +1917,4 @@
"""
return self.parent.MapWindow2D.TextBounds(textinfo, relcoords = True)
-class DragShape:
- """!Class for drawing overlays (based on wxpython demo)"""
- def __init__(self, bmp, id):
- self.bmp = bmp
- self.id = id
- self.pos = (0,0)
- self.shown = True
- self.text = None
- def HitTest(self, pt):
- rect = self.GetRect()
- return rect.InsideXY(pt.x, pt.y)
-
- def GetRect(self):
- return wx.Rect(self.pos[0], self.pos[1],
- self.bmp.GetWidth(), self.bmp.GetHeight())
-
- def Draw(self, dc, op = wx.COPY):
- if self.bmp.Ok():
- memDC = wx.MemoryDC()
- memDC.SelectObject(self.bmp)
-
- dc.Blit(self.pos[0], self.pos[1],
- self.bmp.GetWidth(), self.bmp.GetHeight(),
- memDC, 0, 0, op, True)
-
- return True
- else:
- return False
More information about the grass-commit
mailing list