home *** CD-ROM | disk | FTP | other *** search
- # ***** BEGIN LICENSE BLOCK *****
- # Version: MPL 1.1/GPL 2.0/LGPL 2.1
- #
- # The contents of this file are subject to the Mozilla Public License Version
- # 1.1 (the "License"); you may not use this file except in compliance with
- # the License. You may obtain a copy of the License at
- # http://www.mozilla.org/MPL/
- #
- # Software distributed under the License is distributed on an "AS IS" basis,
- # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- # for the specific language governing rights and limitations under the
- # License.
- #
- # The Original Code is the Python Computer Graphics Kit.
- #
- # The Initial Developer of the Original Code is Matthias Baas.
- # Portions created by the Initial Developer are Copyright (C) 2004
- # the Initial Developer. All Rights Reserved.
- #
- # Contributor(s):
- #
- # Alternatively, the contents of this file may be used under the terms of
- # either the GNU General Public License Version 2 or later (the "GPL"), or
- # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- # in which case the provisions of the GPL or the LGPL are applicable instead
- # of those above. If you wish to allow use of your version of this file only
- # under the terms of either the GPL or the LGPL, and not to allow others to
- # use your version of this file under the terms of the MPL, indicate your
- # decision by deleting the provisions above and replace them with the notice
- # and other provisions required by the GPL or the LGPL. If you do not delete
- # the provisions above, a recipient may use your version of this file under
- # the terms of any one of the MPL, the GPL or the LGPL.
- #
- # ***** END LICENSE BLOCK *****
-
- ## \file keys.py
- ## Contains the Keys class.
-
- import wx
- import string
-
- # Exceptions:
- class InvalidKeyDescription(Exception):
- """Exception class."""
- pass
-
- class KeyNotBound(Exception):
- """Exception class."""
- pass
-
- # Keys
- class Keys(object):
- """This class manages key strokes.
-
- Key bindings correspond to special key attributes. The attribute
- name is the name of the key and the value is a callable object
- that takes no arguments.
-
- Example:
-
- \code
- >>> keys = Keys()
-
- # Bind functions to keys...
- >>> keys.ctrl_c = onExit
- keys.shift_ctrl_tab = onFoo
-
- # Remove a key binding
- >>> del keys.ctrl_c
-
- \endcode
- """
-
- def __init__(self):
-
- # Command dictionary. The keys are the tuples that contain the
- # modifier flags and the key code. The value is a callable object.
- self._commands = {}
-
- # A dictionary that translates wx key codes into a string description
- # The dictionary is built from the WXK_xyz constants
- self._wxkeystrs = {}
- wxkeys = filter(lambda x: x[0:4]=="WXK_", dir(wx))
- for k in wxkeys:
- code = getattr(wx, k)
- self._wxkeystrs[code] = k[4:].capitalize()
-
- # The Window object that uses this key manager
- self._window = None
-
-
- def attach(self, window):
- self._window = window
- wx.EVT_KEY_DOWN(window, self._onKeyDown)
- # wx.EVT_KEY_UP(window, self._onKeyUp)
- # wx.EVT_CHAR(window, self._onChar)
-
- def detach(self):
- pass
-
- def findCommandKeys(self, func):
- """Search the key table for a command and return all associated keys.
-
- \param func (\c callable) The bound function
- \return A list of readable key strings.
- """
-
- res = []
- # Compare all commands...
- for key in self._commands.iterkeys():
- cmd = self._commands[key]
- if func==cmd:
- res.append(self._cmdkey2text(key))
-
- return res
-
- ######################################################################
- ## protected:
-
- # def __setitem__(self, name, value):
- # print "setitem"
- # key = self._str2cmdkey(name)
- # print "Setting",key,"to",value
- # self._commands[key] = value
-
- def _onKeyDown(self, event):
- """Handle a KeyDown event.
-
- Note: This event handler is \b not called if the corresponding
- description text is present in the menu. In that case, the menu
- handles the events itself (a wx feature). But it seems this only
- works with English modifier names.
- """
- print "KeyDown",
- print "KeyCode:",event.GetKeyCode(),"RawKeyCode:",event.GetRawKeyCode()
-
- # Create the key tuple
- key = self._event2cmdkey(event)
- # Check if the key was bound
- if key in self._commands:
- # Call the bound function
- func = self._commands[key]
- func()
- else:
- event.Skip()
-
- def _onKeyUp(self, event):
- # print "KeyUp",
- # print "KeyCode:",event.GetKeyCode(),"RawKeyCode:",event.GetRawKeyCode()
- event.Skip()
-
- def __setattr__(self, name, value):
- if name=="":
- return
- # If the name starts with an underscore then it's not a key description
- if name[0]=="_":
- object.__setattr__(self, name, value)
- return
-
- # Bind key...
-
- # Create the key tuple
- key = self._str2cmdkey(name)
- # Remove an existing binding
- if self._commands.has_key(key):
- self.__delattr__(name)
- # Store the key binding
- self._commands[key] = value
-
- # Update menu items
- self._updateMenu(value)
-
- def __delattr__(self, name):
- # If the name starts with an underscore then it's not a key description
- if name[0]=="_":
- object.__delattr__(self, name)
- return
-
- # Create the key tuple
- key = self._str2cmdkey(name)
- # Check if a key binding exists
- if self._commands.has_key(key):
- func = self._commands[key]
- del self._commands[key]
- # Update menu items
- self._updateMenu(func)
- else:
- raise KeyNotBound, "Key '%s' is not bound to a function."%name
-
-
- def _updateMenu(self, func):
- """Update all menu items that are bound to func."""
- # Check if any menu items have to be updated
- menu = getattr(self._window, "menu", None)
- if menu==None:
- return
- nodes = menu.findCommandNodes(func)
- for n in nodes:
- n.update()
-
-
- def _event2cmdkey(self, event):
- """Convert a key event into a tuple which can be used as key."""
- return (bool(event.ShiftDown()), bool(event.ControlDown()),
- bool(event.AltDown()), bool(event.MetaDown()),
- event.GetKeyCode())
-
- def _str2cmdkey(self, s):
- """Convert a key description string into the key tuple."""
-
- f = s.upper().split("_")
-
- # Check if the modifiers are correct
- for m in f[:-1]:
- if m not in ["SHIFT", "CTRL", "ALT", "META"]:
- raise InvalidKeyDescription, "Key '%s' contains invalid modifiers."%s
-
- # Convert the last argument into a key code
- skey = f[-1]
- if len(skey)==1:
- key = ord(skey)
- else:
- key = getattr(wx, "WXK_%s"%skey, None)
- if key==None:
- raise InvalidKeyDescription, "Key '%s' does not exist."%s
-
- return ("SHIFT" in f, "CTRL" in f, "ALT" in f, "META" in f, key)
-
- def _cmdkey2text(self, key):
- shift, ctrl, alt, meta, key = key
- mods = []
- if shift:
- mods.append("Shift")
- # mods.append("Umschalt")
- if ctrl:
- mods.append("Ctrl")
- # mods.append("Strg")
- if alt:
- mods.append("Alt")
- if meta:
- mods.append("Meta")
-
- ks = self._wxkeystrs.get(key, None)
- if ks==None:
- ks=chr(key)
- mods.append(ks)
-
- return string.join(mods, "+")
-
-
-
-
-
-