Updated FloatCanvas code from Chris
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_8_BRANCH@45725 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
347
wxPython/wx/lib/floatcanvas/GUIMode.py
Normal file
347
wxPython/wx/lib/floatcanvas/GUIMode.py
Normal file
@@ -0,0 +1,347 @@
|
||||
"""
|
||||
|
||||
Module that holds the GUI modes used by FloatCanvas
|
||||
|
||||
|
||||
Note that this can only be imported after a wx.App() has been created.
|
||||
|
||||
This approach was inpired by Christian Blouin, who also wrote the initial
|
||||
version of the code.
|
||||
|
||||
"""
|
||||
|
||||
import wx
|
||||
## fixme: events should live in their own module, so all of FloatCanvas
|
||||
## wouldn't have to be imported here.
|
||||
import FloatCanvas, Resources
|
||||
import numpy as N
|
||||
|
||||
## create all the Cursors, so they don't need to be created each time.
|
||||
if "wxMac" in wx.PlatformInfo: # use 16X16 cursors for wxMac
|
||||
HandCursor = wx.CursorFromImage(Resources.getHand16Image())
|
||||
GrabHandCursor = wx.CursorFromImage(Resources.getGrabHand16Image())
|
||||
|
||||
img = Resources.getMagPlus16Image()
|
||||
img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 6)
|
||||
img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 6)
|
||||
MagPlusCursor = wx.CursorFromImage(img)
|
||||
|
||||
img = Resources.getMagMinus16Image()
|
||||
img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 6)
|
||||
img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 6)
|
||||
MagMinusCursor = wx.CursorFromImage(img)
|
||||
else: # use 24X24 cursors for GTK and Windows
|
||||
HandCursor = wx.CursorFromImage(Resources.getHandImage())
|
||||
GrabHandCursor = wx.CursorFromImage(Resources.getGrabHandImage())
|
||||
|
||||
img = Resources.getMagPlusImage()
|
||||
img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 9)
|
||||
img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 9)
|
||||
MagPlusCursor = wx.CursorFromImage(img)
|
||||
|
||||
img = Resources.getMagMinusImage()
|
||||
img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 9)
|
||||
img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 9)
|
||||
MagMinusCursor = wx.CursorFromImage(img)
|
||||
|
||||
|
||||
class GUIBase:
|
||||
"""
|
||||
Basic Mouse mode and baseclass for other GUImode.
|
||||
|
||||
This one does nothing with any event
|
||||
|
||||
"""
|
||||
def __init__(self, parent):
|
||||
self.parent = parent
|
||||
|
||||
Cursor = wx.NullCursor
|
||||
|
||||
# Handlers
|
||||
def OnLeftDown(self, event):
|
||||
pass
|
||||
def OnLeftUp(self, event):
|
||||
pass
|
||||
def OnLeftDouble(self, event):
|
||||
pass
|
||||
def OnRightDown(self, event):
|
||||
pass
|
||||
def OnRightUp(self, event):
|
||||
pass
|
||||
def OnRightDouble(self, event):
|
||||
pass
|
||||
def OnMiddleDown(self, event):
|
||||
pass
|
||||
def OnMiddleUp(self, event):
|
||||
pass
|
||||
def OnMiddleDouble(self, event):
|
||||
pass
|
||||
def OnWheel(self, event):
|
||||
pass
|
||||
def OnMove(self, event):
|
||||
pass
|
||||
|
||||
def UpdateScreen(self):
|
||||
"""
|
||||
Update gets called if the screen has been repainted in the middle of a zoom in
|
||||
so the Rubber Band Box can get updated
|
||||
"""
|
||||
pass
|
||||
|
||||
class GUIMouse(GUIBase):
|
||||
"""
|
||||
|
||||
Mouse mode checks for a hit test, and if nothing is hit,
|
||||
raises a FloatCanvas mouse event for each event.
|
||||
|
||||
"""
|
||||
|
||||
Cursor = wx.NullCursor
|
||||
|
||||
# Handlers
|
||||
def OnLeftDown(self, event):
|
||||
EventType = FloatCanvas.EVT_FC_LEFT_DOWN
|
||||
if not self.parent.HitTest(event, EventType):
|
||||
self.parent._RaiseMouseEvent(event, EventType)
|
||||
|
||||
def OnLeftUp(self, event):
|
||||
EventType = FloatCanvas.EVT_FC_LEFT_UP
|
||||
if not self.parent.HitTest(event, EventType):
|
||||
self.parent._RaiseMouseEvent(event, EventType)
|
||||
|
||||
def OnLeftDouble(self, event):
|
||||
EventType = FloatCanvas.EVT_FC_LEFT_DCLICK
|
||||
if not self.parent.HitTest(event, EventType):
|
||||
self.parent._RaiseMouseEvent(event, EventType)
|
||||
|
||||
def OnMiddleDown(self, event):
|
||||
EventType = FloatCanvas.EVT_FC_MIDDLE_DOWN
|
||||
if not self.parent.HitTest(event, EventType):
|
||||
self.parent._RaiseMouseEvent(event, EventType)
|
||||
|
||||
def OnMiddleUp(self, event):
|
||||
EventType = FloatCanvas.EVT_FC_MIDDLE_UP
|
||||
if not self.parent.HitTest(event, EventType):
|
||||
self.parent._RaiseMouseEvent(event, EventType)
|
||||
|
||||
def OnMiddleDouble(self, event):
|
||||
EventType = FloatCanvas.EVT_FC_MIDDLE_DCLICK
|
||||
if not self.parent.HitTest(event, EventType):
|
||||
self.parent._RaiseMouseEvent(event, EventType)
|
||||
|
||||
def OnRightDown(self, event):
|
||||
EventType = FloatCanvas.EVT_FC_RIGHT_DOWN
|
||||
if not self.parent.HitTest(event, EventType):
|
||||
self.parent._RaiseMouseEvent(event, EventType)
|
||||
|
||||
def OnRightUp(self, event):
|
||||
EventType = FloatCanvas.EVT_FC_RIGHT_UP
|
||||
if not self.parent.HitTest(event, EventType):
|
||||
self.parent._RaiseMouseEvent(event, EventType)
|
||||
|
||||
def OnRightDouble(self, event):
|
||||
EventType = FloatCanvas.EVT_FC_RIGHT_DCLICK
|
||||
if not self.parent.HitTest(event, EventType):
|
||||
self.parent._RaiseMouseEvent(event, EventType)
|
||||
|
||||
def OnWheel(self, event):
|
||||
EventType = FloatCanvas.EVT_FC_MOUSEWHEEL
|
||||
self.parent._RaiseMouseEvent(event, EventType)
|
||||
|
||||
def OnMove(self, event):
|
||||
## The Move event always gets raised, even if there is a hit-test
|
||||
self.parent.MouseOverTest(event)
|
||||
self.parent._RaiseMouseEvent(event,FloatCanvas.EVT_FC_MOTION)
|
||||
|
||||
|
||||
class GUIMove(GUIBase):
|
||||
|
||||
Cursor = HandCursor
|
||||
GrabCursor = GrabHandCursor
|
||||
def __init__(self, parent):
|
||||
GUIBase.__init__(self, parent)
|
||||
self.StartMove = None
|
||||
self.PrevMoveXY = None
|
||||
|
||||
def OnLeftDown(self, event):
|
||||
self.parent.SetCursor(self.GrabCursor)
|
||||
self.parent.CaptureMouse()
|
||||
self.StartMove = N.array( event.GetPosition() )
|
||||
self.PrevMoveXY = (0,0)
|
||||
|
||||
def OnLeftUp(self, event):
|
||||
if self.StartMove is not None:
|
||||
StartMove = self.StartMove
|
||||
EndMove = N.array(event.GetPosition())
|
||||
DiffMove = StartMove-EndMove
|
||||
if N.sum(DiffMove**2) > 16:
|
||||
self.parent.MoveImage(DiffMove, 'Pixel')
|
||||
self.StartMove = None
|
||||
self.parent.SetCursor(self.Cursor)
|
||||
|
||||
def OnMove(self, event):
|
||||
# Allways raise the Move event.
|
||||
self.parent._RaiseMouseEvent(event,FloatCanvas.EVT_FC_MOTION)
|
||||
if event.Dragging() and event.LeftIsDown() and not self.StartMove is None:
|
||||
xy1 = N.array( event.GetPosition() )
|
||||
wh = self.parent.PanelSize
|
||||
xy_tl = xy1 - self.StartMove
|
||||
dc = wx.ClientDC(self.parent)
|
||||
dc.BeginDrawing()
|
||||
x1,y1 = self.PrevMoveXY
|
||||
x2,y2 = xy_tl
|
||||
w,h = self.parent.PanelSize
|
||||
##fixme: This sure could be cleaner!
|
||||
if x2 > x1 and y2 > y1:
|
||||
xa = xb = x1
|
||||
ya = yb = y1
|
||||
wa = w
|
||||
ha = y2 - y1
|
||||
wb = x2- x1
|
||||
hb = h
|
||||
elif x2 > x1 and y2 <= y1:
|
||||
xa = x1
|
||||
ya = y1
|
||||
wa = x2 - x1
|
||||
ha = h
|
||||
xb = x1
|
||||
yb = y2 + h
|
||||
wb = w
|
||||
hb = y1 - y2
|
||||
elif x2 <= x1 and y2 > y1:
|
||||
xa = x1
|
||||
ya = y1
|
||||
wa = w
|
||||
ha = y2 - y1
|
||||
xb = x2 + w
|
||||
yb = y1
|
||||
wb = x1 - x2
|
||||
hb = h - y2 + y1
|
||||
elif x2 <= x1 and y2 <= y1:
|
||||
xa = x2 + w
|
||||
ya = y1
|
||||
wa = x1 - x2
|
||||
ha = h
|
||||
xb = x1
|
||||
yb = y2 + h
|
||||
wb = w
|
||||
hb = y1 - y2
|
||||
|
||||
dc.SetPen(wx.TRANSPARENT_PEN)
|
||||
dc.SetBrush(self.parent.BackgroundBrush)
|
||||
dc.DrawRectangle(xa, ya, wa, ha)
|
||||
dc.DrawRectangle(xb, yb, wb, hb)
|
||||
self.PrevMoveXY = xy_tl
|
||||
if self.parent._ForeDrawList:
|
||||
dc.DrawBitmapPoint(self.parent._ForegroundBuffer,xy_tl)
|
||||
else:
|
||||
dc.DrawBitmapPoint(self.parent._Buffer,xy_tl)
|
||||
dc.EndDrawing()
|
||||
|
||||
def OnWheel(self, event):
|
||||
"""
|
||||
By default, zoom in/out by a 0.1 factor per Wheel event.
|
||||
"""
|
||||
if event.GetWheelRotation() < 0:
|
||||
self.parent.Zoom(0.9)
|
||||
else:
|
||||
self.parent.Zoom(1.1)
|
||||
|
||||
class GUIZoomIn(GUIBase):
|
||||
|
||||
Cursor = MagPlusCursor
|
||||
|
||||
def __init__(self, parent):
|
||||
GUIBase.__init__(self, parent)
|
||||
self.StartRBBox = None
|
||||
self.PrevRBBox = None
|
||||
|
||||
def OnLeftDown(self, event):
|
||||
self.StartRBBox = N.array( event.GetPosition() )
|
||||
self.PrevRBBox = None
|
||||
self.parent.CaptureMouse()
|
||||
|
||||
def OnLeftUp(self, event):
|
||||
#if self.parent.HasCapture():
|
||||
# self.parent.ReleaseMouse()
|
||||
if event.LeftUp() and not self.StartRBBox is None:
|
||||
self.PrevRBBox = None
|
||||
EndRBBox = event.GetPosition()
|
||||
StartRBBox = self.StartRBBox
|
||||
# if mouse has moved less that ten pixels, don't use the box.
|
||||
if ( abs(StartRBBox[0] - EndRBBox[0]) > 10
|
||||
and abs(StartRBBox[1] - EndRBBox[1]) > 10 ):
|
||||
EndRBBox = self.parent.PixelToWorld(EndRBBox)
|
||||
StartRBBox = self.parent.PixelToWorld(StartRBBox)
|
||||
BB = N.array(((min(EndRBBox[0],StartRBBox[0]),
|
||||
min(EndRBBox[1],StartRBBox[1])),
|
||||
(max(EndRBBox[0],StartRBBox[0]),
|
||||
max(EndRBBox[1],StartRBBox[1]))),N.float_)
|
||||
self.parent.ZoomToBB(BB)
|
||||
else:
|
||||
Center = self.parent.PixelToWorld(StartRBBox)
|
||||
self.parent.Zoom(1.5,Center)
|
||||
self.StartRBBox = None
|
||||
|
||||
def OnMove(self, event):
|
||||
# Allways raise the Move event.
|
||||
self.parent._RaiseMouseEvent(event,FloatCanvas.EVT_FC_MOTION)
|
||||
if event.Dragging() and event.LeftIsDown() and not (self.StartRBBox is None):
|
||||
xy0 = self.StartRBBox
|
||||
xy1 = N.array( event.GetPosition() )
|
||||
wh = abs(xy1 - xy0)
|
||||
wh[0] = max(wh[0], int(wh[1]*self.parent.AspectRatio))
|
||||
wh[1] = int(wh[0] / self.parent.AspectRatio)
|
||||
xy_c = (xy0 + xy1) / 2
|
||||
dc = wx.ClientDC(self.parent)
|
||||
dc.BeginDrawing()
|
||||
dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
|
||||
dc.SetBrush(wx.TRANSPARENT_BRUSH)
|
||||
dc.SetLogicalFunction(wx.XOR)
|
||||
if self.PrevRBBox:
|
||||
dc.DrawRectanglePointSize(*self.PrevRBBox)
|
||||
self.PrevRBBox = ( xy_c - wh/2, wh )
|
||||
dc.DrawRectanglePointSize( *self.PrevRBBox )
|
||||
dc.EndDrawing()
|
||||
|
||||
def UpdateScreen(self):
|
||||
"""
|
||||
Update gets called if the screen has been repainted in the middle of a zoom in
|
||||
so the Rubber Band Box can get updated
|
||||
"""
|
||||
if self.PrevRBBox is not None:
|
||||
dc = wx.ClientDC(self.parent)
|
||||
dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH))
|
||||
dc.SetBrush(wx.TRANSPARENT_BRUSH)
|
||||
dc.SetLogicalFunction(wx.XOR)
|
||||
dc.DrawRectanglePointSize(*self.PrevRBBox)
|
||||
|
||||
def OnRightDown(self, event):
|
||||
self.parent.Zoom(1/1.5, event.GetPosition(), centerCoords="pixel")
|
||||
|
||||
def OnWheel(self, event):
|
||||
if event.GetWheelRotation() < 0:
|
||||
self.parent.Zoom(0.9)
|
||||
else:
|
||||
self.parent.Zoom(1.1)
|
||||
|
||||
class GUIZoomOut(GUIBase):
|
||||
|
||||
Cursor = MagMinusCursor
|
||||
|
||||
def OnLeftDown(self, event):
|
||||
self.parent.Zoom(1/1.5, event.GetPosition(), centerCoords="pixel")
|
||||
|
||||
def OnRightDown(self, event):
|
||||
self.parent.Zoom(1.5, event.GetPosition(), centerCoords="pixel")
|
||||
|
||||
def OnWheel(self, event):
|
||||
if event.GetWheelRotation() < 0:
|
||||
self.parent.Zoom(0.9)
|
||||
else:
|
||||
self.parent.Zoom(1.1)
|
||||
|
||||
def OnMove(self, event):
|
||||
# Allways raise the Move event.
|
||||
self.parent._RaiseMouseEvent(event,FloatCanvas.EVT_FC_MOTION)
|
||||
|
Reference in New Issue
Block a user