]> git.saurik.com Git - wxWidgets.git/commitdiff
Updates for MouseGestures
authorRobin Dunn <robin@alldunn.com>
Mon, 28 Feb 2005 20:03:35 +0000 (20:03 +0000)
committerRobin Dunn <robin@alldunn.com>
Mon, 28 Feb 2005 20:03:35 +0000 (20:03 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@32493 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

wxPython/demo/MouseGestures.py
wxPython/wx/lib/gestures.py

index 3083414f159d43a9afcdf624daa9b170839b864e..0374a0b336ef3ecff00b9ce6cd4de4b3c59be5bc 100644 (file)
@@ -5,11 +5,11 @@
 #Thanks to Robin Dunn for taking the time to show me how to do this
 #via the mailing list.
 
-#Version 0.0.0 ALPHA
+#Version 0.0.0
 
 #This is a hacked version of DragAndDrop.py from the wxPython demo 2.5.2.8
 
-import  wx, wx.stc
+import wx, wx.stc, wx.lib.dialogs
 from wx.lib.gestures import MouseGestures
 
 #ToDo:
@@ -24,6 +24,9 @@ class TestPanel(wx.Panel):
         wx.Panel.__init__(self, parent, -1)
 
         ID_GESTURE = wx.NewId()
+        ID_MOUSE = wx.NewId()
+        ID_MODIFIER = wx.NewId()
+        ID_VISIBLE = wx.NewId()
 
         self.log = log
 
@@ -33,14 +36,22 @@ class TestPanel(wx.Panel):
         
         self.mg.SetGesturesVisible(True)
         
+        self.mg.AddGesture('LR', self.ShowSomethingClever, 'Left then Right!')
+        self.mg.AddGesture('39', self.ShowSomethingClever, 'You made a V!')
         self.mg.AddGesture('L', self.LogSomethingClever, 'You moved left')
         self.mg.AddGesture('9', self.LogSomethingClever, 'You moved right and up')
         self.mg.AddGesture('U', self.LogSomethingClever, 'You moved up')
-        self.mg.AddGesture('DR', self.OnDownThenRight)        
+        self.mg.AddGesture('DR', self.OnDownThenRight)
+        self.mg.AddGesture('LDRU', self.SetToBlue)
+        self.mg.AddGesture('RDLU', self.SetToOrange)
         
         #Widgets:
             
         self.btnAddGesture = wx.Button(self, ID_GESTURE, 'Add New Gesture')
+        self.btnChangeMouseButton = wx.Button(self, ID_MOUSE, 'Change Mouse Button')
+        self.btnChangeModifier = wx.Button(self, ID_MODIFIER, 'Change Modifier')
+        self.btnToggleVisible = wx.ToggleButton(self, ID_VISIBLE, 'Toggle Gestures Visible')
+        self.btnToggleVisible.SetValue(True)
         
         msg = "Mouse Gestures"
         text = wx.StaticText(self, -1, "", style=wx.ALIGN_CENTRE)
@@ -49,25 +60,37 @@ class TestPanel(wx.Panel):
 
         w,h = text.GetTextExtent(msg)
         text.SetSize(wx.Size(w,h+1))
-        text.SetForegroundColour(wx.BLUE)        
+        text.SetForegroundColour(wx.BLUE)
+        
+        self.SetBackgroundColour(wx.WHITE)
         
         #Sizer:
         outsideSizer = wx.BoxSizer(wx.VERTICAL)
         
+        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
+        
         outsideSizer.Add(text, 0, wx.EXPAND|wx.ALL, 5)
         outsideSizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND)
         outsideSizer.Add(wx.StaticText(self, -1, '   '), 0, wx.EXPAND)
         outsideSizer.Add(wx.StaticText(self, -1, 'Hold The Middle Mouse Button Down to Gesticulate'), 0, wx.EXPAND)
-        outsideSizer.Add(wx.StaticText(self, -1, 'Left, The Diagonal Up/Right, Down Then Right, and Up are Preset'), 0, wx.EXPAND)
+        outsideSizer.Add(wx.StaticText(self, -1, 'Left Then Right, Left, The Diagonal Up/Right, Down Then Right, Diagonal Down/Right Then Diagonal Up/Right, and Up are Preset'), 0, wx.EXPAND)
+        outsideSizer.Add(wx.StaticText(self, -1, 'Left,Down,Right,Up Sets the line colour to Blue.'), 0, wx.EXPAND)
+        outsideSizer.Add(wx.StaticText(self, -1, 'Right,Down,Left,Up Sets the line colour to Orange.'), 0, wx.EXPAND)
         outsideSizer.Add(wx.StaticText(self, -1, '   '), 0, wx.EXPAND)
-        outsideSizer.Add(self.btnAddGesture, 0, wx.SHAPED)
+        btnSizer.Add(self.btnAddGesture, 0, wx.SHAPED)
+        btnSizer.Add(self.btnChangeMouseButton, 0, wx.SHAPED)
+        btnSizer.Add(self.btnChangeModifier, 0, wx.SHAPED)
+        btnSizer.Add(self.btnToggleVisible, 0, wx.SHAPED)
+        outsideSizer.Add(btnSizer, 0, wx.SHAPED)
         
         self.SetAutoLayout(True)
         self.SetSizer(outsideSizer)
 
-
         #Events:
-        self.Bind(wx.EVT_BUTTON, self.OnAddGesture, id=ID_GESTURE)        
+        self.Bind(wx.EVT_BUTTON, self.OnAddGesture, id=ID_GESTURE)
+        self.Bind(wx.EVT_BUTTON, self.OnChangeMouseButton, id=ID_MOUSE)
+        self.Bind(wx.EVT_BUTTON, self.OnChangeModifiers, id=ID_MODIFIER)
+        self.Bind(wx.EVT_TOGGLEBUTTON, self.OnToggleVisible, id=ID_VISIBLE)
 
     def LogSomethingClever(self, somethingclever):
         self.log.WriteText(somethingclever)
@@ -77,16 +100,73 @@ class TestPanel(wx.Panel):
         answer1 = d.ShowModal()
         gesture = d.GetValue()
         d.Destroy()
+        
         d = wx.TextEntryDialog(self, 'Print the following text on "%s":' % gesture, "Gesture Action", "")
         answer2 = d.ShowModal()
         text = d.GetValue()
         d.Destroy()
+        
         if (answer1 == wx.ID_OK) and (answer2 == wx.ID_OK):
             self.mg.AddGesture(gesture.upper(), self.LogSomethingClever, text)
+    
+    def OnChangeModifiers(self, event):
+        choices = [wx.WXK_CONTROL, wx.WXK_SHIFT, wx.WXK_ALT]
+        schoices = ['Control', 'Shift', 'Alt']
+        
+        d = wx.lib.dialogs.MultipleChoiceDialog(self, 'Select Modifier Keys:\n(Select None if you do not want to use modifier keys\n\n', "Change Modifier Keys", schoices)
+        answer = d.ShowModal()
+        tuply = d.GetValue()
+        d.Destroy()
+        
+        if (answer == wx.ID_OK):
+            if len(tuply) > 0:
+                modifiers = []
+                modstring = ''
+                for x in tuply:
+                    modifiers.append(choices[x])
+                    modstring += schoices[x] + ' '
+                self.mg.SetModifiers(modifiers)
+                self.log.WriteText('Set Modifiers to: ' + modstring)
+            else:
+                self.mg.SetModifiers()
+                self.log.WriteText('UnSet All Modifiers')
+    
+    def OnChangeMouseButton(self, event):
+        choices = [wx.MOUSE_BTN_LEFT, wx.MOUSE_BTN_MIDDLE, wx.MOUSE_BTN_RIGHT]
+        schoices = ['Left', 'Middle', 'Right']
+        d = wx.SingleChoiceDialog(self, "Set Mouse Button To", "Change Mouse Button", schoices, wx.OK|wx.CANCEL)
+        d.SetSize(wx.Size(250, 200))
+        answer = d.ShowModal()
+        i = d.GetSelection()
+        d.Destroy()
+        if (answer == wx.ID_OK):
+            self.mg.SetMouseButton(choices[i])
+            self.log.WriteText('Set the Mouse Button to ' + schoices[i])
         
     def OnDownThenRight(self):
         self.log.WriteText('You made an "L"!')
 
+    def OnToggleVisible(self, event):
+        visual = self.btnToggleVisible.GetValue()
+        self.mg.SetGesturesVisible(visual)
+        if visual:
+            self.log.WriteText('Made Gestures Visible')
+        else:
+            self.log.WriteText('Made Gestures Invisible')
+
+    def SetToBlue(self):
+        self.mg.SetGesturePen(wx.Colour(0, 144, 255), 5)
+        self.log.WriteText('Set Gesture Colour to Blue')
+        
+    def SetToOrange(self):
+        self.mg.SetGesturePen(wx.Colour(255, 156, 0), 5)
+        self.log.WriteText('Set Gesture Colour to Orange')
+
+    def ShowSomethingClever(self, somethingclever):
+        d = wx.MessageDialog(self, somethingclever, 'Mouse Gesture Action', wx.OK)
+        d.ShowModal()
+        d.Destroy()
+
 #----------------------------------------------------------------------
 
 def runTest(frame, nb, log):
@@ -113,3 +193,4 @@ if __name__ == '__main__':
     import run
     run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])
 
+
index b4e8beea03e83459ca739a64edea305d3bb08fb4..0ab9d149ce81045c35fff95500aa8ae038790be9 100644 (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.
 #is not greater than twice the lesser, only the grater value
 #is counted.
 
-#ToDo:
 
-#Add in modifier code (Ctrl, Alt, etc).
+#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:
 
-#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()
\ No newline at end of file