Updates for MouseGestures

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@32493 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2005-02-28 20:03:35 +00:00
parent 4860d40db4
commit 7a0c9b3917
2 changed files with 190 additions and 63 deletions

View File

@@ -1,6 +1,6 @@
#Mouse Gestures
#Version 0.0.0 ALPHA
#Version 0.0.1
#By Daniel Pozmanter
#drpython@bluebottle.com
@@ -9,17 +9,15 @@
#This is a class to add Mouse Gestures to a program.
#It can be used in two ways:
#
#1. Automatic:
# Automatically runs mouse gestures.
# You need to set the gestures, and their associated actions,
# as well as the Mouse Button/Modifiers to use.
#
# (Mouse Buttons are set in init)
#1. Automatic:
# Automatically runs mouse gestures.
# You need to set the gestures, and their associated actions,
# as well as the Mouse Button/Modifiers to use.
#
#2. Manual:
# Same as above, but you do not need to set the mouse button/modifiers.
# You can launch this from events as you wish.
# Same as above, but you do not need to set the mouse button/modifiers.
# You can launch this from events as you wish.
#
#An example is provided in the demo.
#The parent window is where the mouse events will be recorded.
@@ -29,7 +27,7 @@
#Start() starts recording mouse movement.
#End() stops the recording, compiles all the gestures into a list,
#and looks through the registered gestures to find a match.
#The first matchs associated action is then run.
#The first matchs associated action is then run.
#The marginoferror is how much to forgive when calculating movement:
#If the margin is 25, then movement less than 25 pixels will not be detected.
@@ -57,34 +55,46 @@
#is not greater than twice the lesser, only the grater value
#is counted.
#In automatic mode, EVT_MOUSE_EVENTS is used.
#This allows the user to change the mouse button/modifiers at runtime.
###########################################
'''
Changelog:
0.0.1: Treats a mouse leaving event as mouse up.
(Bug Report, Thanks Peter Damoc).
0.0.0: Initial Release.
'''
###########################################
#ToDo:
#Add in modifier code (Ctrl, Alt, etc).
#SetGestureLine(wx.Colour(), int width)
#Fully Implement Manual Mode
#Add "Ends With": AddGestureEndsWith(self, gesture, action, args)
#Add "Starts With": AddGestuteStartsWith(self, gesture, action, args)
#At the moment, the mouse button can only be set at startup.
#I could use UnBind, but this may limit the wxPython version being used,
#and, what if the user has other events bound?
#So I think, if the user wants to change the mouse button at runtime,
#the best solution is to use manual mode.
#For better control of when the gesture starts and stops,
#use manual mode.
#At the moment, you need to Bind the OnMouseMotion event if you want to use
#manual mode.
import wx
class MouseGestures:
def __init__(self, parent, Auto=True, MouseButton=wx.MOUSE_BTN_MIDDLE):
self.parent = parent
self.gestures = []
self.actions = []
self.actionarguments = []
self.mousebutton = MouseButton
self.modifiers = 0
self.modifiers = []
self.recording = False
@@ -103,12 +113,22 @@ class MouseGestures:
self.SetAuto(Auto)
def Action(self, gesture):
if gesture in self.gestures:
i = self.gestures.index(gesture)
apply(self.actions[i], self.actionarguments[i])
def _check_modifiers(self, event):
'''Internal: Returns True if all needed modifiers are down
for the given event.'''
if len(self.modifiers) > 0:
good = True
if wx.WXK_CONTROL in self.modifiers:
good = good and event.ControlDown()
if wx.WXK_SHIFT in self.modifiers:
good = good and event.ShiftDown()
if wx.WXK_ALT in self.modifiers:
good = good and event.AltDown()
return good
return True
def AddGesture(self, gesture, action, *args):
'''Registers a gesture, and an associated function, with any arguments needed.'''
#Make Sure not a duplicate:
self.RemoveGesture(gesture)
@@ -116,13 +136,21 @@ class MouseGestures:
self.actions.append(action)
self.actionarguments.append(args)
def DoAction(self, gesture):
'''If the gesture is in the array of registered gestures, run the associated function.'''
if gesture in self.gestures:
i = self.gestures.index(gesture)
apply(self.actions[i], self.actionarguments[i])
def End(self):
'''Stops recording the points to create the mouse gesture from,
and creates the mouse gesture, returns the result as a string.'''
self.recording = False
#Figure out the gestures (Look for occurances of 5 in a row or more):
tempstring = '0'
possiblechange = '0'
possiblechange = '0'
directions = ''
@@ -132,7 +160,7 @@ class MouseGestures:
if g == possiblechange:
tempstring = g + g
else:
possiblechange = g
possiblechange = g
else:
tempstring += g
if len(tempstring) >= self.wobbletolerance:
@@ -143,10 +171,14 @@ class MouseGestures:
else:
directions += g
tempstring = '0'
if self.showgesture:
self.parent.Refresh()
return directions
def GetDirection(self, point1, point2):
'''Gets the direction between two points.'''
#point1 is the old point
#point2 is current
@@ -172,7 +204,7 @@ class MouseGestures:
elif av > ah:
if (av / ah) > 2:
horizontal = 0
horizontalchange = False
horizontalchange = False
if horizontalchange and verticalchange:
#Diagonal
@@ -183,7 +215,7 @@ class MouseGestures:
elif (horizontal < 0) and (vertical > 0):
return '1'
else:
return '7'
return '7'
else:
#Straight Line
if horizontalchange:
@@ -196,16 +228,13 @@ class MouseGestures:
return 'D'
else:
return 'U'
def OnEnd(self, event):
result = self.End()
self.Action(result)
event.Skip()
def GetRecording(self):
'''Returns whether or not Gesture Recording has started.'''
return self.recording
def OnMotion(self, event):
'''Internal. Used if Start() has been run'''
if self.recording:
currentposition = event.GetPosition()
if self.lastposition != (-1, -1):
@@ -214,50 +243,67 @@ class MouseGestures:
#Draw it!
px1, py1 = self.parent.ClientToScreen(self.lastposition)
px2, py2 = self.parent.ClientToScreen(currentposition)
self.dc.DrawLine(px1, py1, px2, py2)
self.dc.DrawLine(px1, py1, px2, py2)
self.lastposition = currentposition
event.Skip()
def OnStart(self, event):
self.Start()
def OnMouseEvent(self, event):
'''Internal. Used in Auto Mode.'''
if event.ButtonDown(self.mousebutton) and self._check_modifiers(event):
self.Start()
elif (event.ButtonUp(self.mousebutton) or event.Leaving()) and self.GetRecording():
result = self.End()
self.DoAction(result)
event.Skip()
def RemoveGesture(self, gesture):
'''Removes a gesture, and its associated action'''
if gesture in self.gestures:
i = self.gestures.index(gesture)
del self.gestures[i]
del self.actions[i]
del self.actionarguments[i]
def SetAuto(self, auto):
#I was not sure about making this part of init, so I left it as its own method for now.
'''Warning: Once auto is set, it stays set, unless you manually use UnBind'''
if auto:
if self.mousebutton == wx.MOUSE_BTN_LEFT:
self.parent.Bind(wx.EVT_LEFT_DOWN, self.OnStart)
self.parent.Bind(wx.EVT_LEFT_UP, self.OnEnd)
elif self.mousebutton == wx.MOUSE_BTN_MIDDLE:
self.parent.Bind(wx.EVT_MIDDLE_DOWN, self.OnStart)
self.parent.Bind(wx.EVT_MIDDLE_UP, self.OnEnd)
elif self.mousebutton == wx.MOUSE_BTN_RIGHT:
self.parent.Bind(wx.EVT_RIGHT_DOWN, self.OnStart)
self.parent.Bind(wx.EVT_RIGHT_UP, self.OnEnd)
self.parent.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvent)
self.parent.Bind(wx.EVT_MOTION, self.OnMotion)
def SetGesturePen(self, pen):
'''Sets the wx pen used to visually represent each gesture'''
self.pen = pen
self.dc.SetPen(self.pen)
def SetGesturePen(self, colour, width):
'''Sets the colour and width of the line drawn to visually represent each gesture'''
self.pen = wx.Pen(colour, width)
self.dc.SetPen(self.pen)
def SetGesturesVisible(self, vis):
'''Sets whether a line is drawn to visually represent each gesture'''
self.showgesture = vis
def SetModifiers(self, modifers):
def SetModifiers(self, modifiers=[]):
'''Takes an array of wx Key constants (Control, Shift, and/or Alt).
Leave empty to unset all modifiers.'''
self.modifiers = modifiers
def SetMouseButton(self, mousebutton):
'''Takes the wx constant for the target mousebutton'''
self.mousebutton = mousebutton
def SetWobbleTolerance(self, wobbletolerance):
'''Sets just how much wobble this class can take!'''
self.WobbleTolerance = wobbletolerance
def Start(self):
'''Starts recording the points to create the mouse gesture from'''
self.recording = True
self.rawgesture = ''
self.rawgesture = ''
self.lastposition = (-1, -1)
if self.showgesture:
if self.showgesture:
self.parent.Refresh()