X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/51c5e1f21eb54f2457269258040b7cd360cb3f69..db679b8c836e69c111cdc31e62cf92cebe4f938f:/wxPython/wx/lib/gestures.py?ds=sidebyside diff --git a/wxPython/wx/lib/gestures.py b/wxPython/wx/lib/gestures.py index b4e8beea03..eaf47ace9f 100644 --- a/wxPython/wx/lib/gestures.py +++ b/wxPython/wx/lib/gestures.py @@ -1,90 +1,101 @@ #Mouse Gestures -#Version 0.0.0 ALPHA +#Version 0.0.1 #By Daniel Pozmanter #drpython@bluebottle.com #Released under the terms of the wxWindows License. -#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) -# -#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. -# -#An example is provided in the demo. -#The parent window is where the mouse events will be recorded. -#(So if you want to record them in a pop up window, use manual mode, -#and set the pop up as the parent). -# -#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. +""" +This is a class to add Mouse Gestures to a program. +It can be used in two ways: -#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. +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. -#Recognized: L, R, U, D, 1, 3, 7, 9 +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. -#Styles: Manual (Automatic By Default), DisplayNumbersForDiagonals (Off By Default). -#Not Yet Implemented +An example is provided in the demo. +The parent window is where the mouse events will be recorded. +(So if you want to record them in a pop up window, use manual mode, +and set the pop up as the parent). -#The criteria for a direction is as follows: -#x in a row. (Where x is the WobbleTolerance). -#So if the WobbleTolerance is 9 -# 'URUUUUUUUUUUUUUUURUURUUUU1' is Up. +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 higher this number, the less sensitive this class is. -#So the more likely something like 1L will translate to 1. +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. -#This is good, since the mouse does tend to wobble somewhat, -#and a higher number allows for this. +Recognized: L, R, U, D, 1, 3, 7, 9 -#To change this, use SetWobbleTolerance +Styles: Manual (Automatic By Default), DisplayNumbersForDiagonals (Off By Default). +Not Yet Implemented -#Also, to help with recognition of a diagonal versus -#a vey messy straight line, if the greater absolute value -#is not greater than twice the lesser, only the grater value -#is counted. +The criteria for a direction is as follows: +x in a row. (Where x is the WobbleTolerance). +So if the WobbleTolerance is 9 + 'URUUUUUUUUUUUUUUURUURUUUU1' is Up. -#ToDo: +The higher this number, the less sensitive this class is. +So the more likely something like 1L will translate to 1. + +This is good, since the mouse does tend to wobble somewhat, +and a higher number allows for this. + +To change this, use SetWobbleTolerance + +Also, to help with recognition of a diagonal versus +a vey messy straight line, if the greater absolute value +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. +""" -#Add in modifier code (Ctrl, Alt, etc). +########################################### + +''' +Changelog: +0.0.1: Treats a mouse leaving event as mouse up. + (Bug Report, Thanks Peter Damoc). + + +0.0.0: Initial Release. +''' + +########################################### +#ToDo: -#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 +114,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 +137,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 +161,7 @@ class MouseGestures: if g == possiblechange: tempstring = g + g else: - possiblechange = g + possiblechange = g else: tempstring += g if len(tempstring) >= self.wobbletolerance: @@ -143,10 +172,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 +205,7 @@ class MouseGestures: elif av > ah: if (av / ah) > 2: horizontal = 0 - horizontalchange = False + horizontalchange = False if horizontalchange and verticalchange: #Diagonal @@ -183,7 +216,7 @@ class MouseGestures: elif (horizontal < 0) and (vertical > 0): return '1' else: - return '7' + return '7' else: #Straight Line if horizontalchange: @@ -196,16 +229,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 +244,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: - self.parent.Refresh() \ No newline at end of file + if self.showgesture: + self.parent.Refresh()