123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- import traceback
-
- import win32api
- import win32con
- import win32ui
-
- from . import IDLEenvironment, keycodes
-
- HANDLER_ARGS_GUESS = 0
- HANDLER_ARGS_NATIVE = 1
- HANDLER_ARGS_IDLE = 2
- HANDLER_ARGS_EXTENSION = 3
-
- next_id = 5000
-
- event_to_commands = {} # dict of integer IDs to event names.
- command_to_events = {} # dict of event names to int IDs
-
-
- def assign_command_id(event, id=0):
- global next_id
- if id == 0:
- id = event_to_commands.get(event, 0)
- if id == 0:
- id = next_id
- next_id = next_id + 1
- # Only map the ones we allocated - specified ones are assumed to have a handler
- command_to_events[id] = event
- event_to_commands[event] = id
- return id
-
-
- class SendCommandHandler:
- def __init__(self, cmd):
- self.cmd = cmd
-
- def __call__(self, *args):
- win32ui.GetMainFrame().SendMessage(win32con.WM_COMMAND, self.cmd)
-
-
- class Binding:
- def __init__(self, handler, handler_args_type):
- self.handler = handler
- self.handler_args_type = handler_args_type
-
-
- class BindingsManager:
- def __init__(self, parent_view):
- self.parent_view = parent_view
- self.bindings = {} # dict of Binding instances.
- self.keymap = {}
-
- def prepare_configure(self):
- self.keymap = {}
-
- def complete_configure(self):
- for id in command_to_events.keys():
- self.parent_view.HookCommand(self._OnCommand, id)
-
- def close(self):
- self.parent_view = self.bindings = self.keymap = None
-
- def report_error(self, problem):
- try:
- win32ui.SetStatusText(problem, 1)
- except win32ui.error:
- # No status bar!
- print(problem)
-
- def update_keymap(self, keymap):
- self.keymap.update(keymap)
-
- def bind(self, event, handler, handler_args_type=HANDLER_ARGS_GUESS, cid=0):
- if handler is None:
- handler = SendCommandHandler(cid)
- self.bindings[event] = self._new_binding(handler, handler_args_type)
- self.bind_command(event, cid)
-
- def bind_command(self, event, id=0):
- "Binds an event to a Windows control/command ID"
- id = assign_command_id(event, id)
- return id
-
- def get_command_id(self, event):
- id = event_to_commands.get(event)
- if id is None:
- # See if we even have an event of that name!?
- if event not in self.bindings:
- return None
- id = self.bind_command(event)
- return id
-
- def _OnCommand(self, id, code):
- event = command_to_events.get(id)
- if event is None:
- self.report_error("No event associated with event ID %d" % id)
- return 1
- return self.fire(event)
-
- def _new_binding(self, event, handler_args_type):
- return Binding(event, handler_args_type)
-
- def _get_IDLE_handler(self, ext, handler):
- try:
- instance = self.parent_view.idle.IDLEExtension(ext)
- name = handler.replace("-", "_") + "_event"
- return getattr(instance, name)
- except (ImportError, AttributeError):
- msg = "Can not find event '%s' in IDLE extension '%s'" % (handler, ext)
- self.report_error(msg)
- return None
-
- def fire(self, event, event_param=None):
- # Fire the specified event. Result is native Pythonwin result
- # (ie, 1==pass one, 0 or None==handled)
-
- # First look up the event directly - if there, we are set.
- binding = self.bindings.get(event)
- if binding is None:
- # If possible, find it!
- # A native method name
- handler = getattr(self.parent_view, event + "Event", None)
- if handler is None:
- # Can't decide if I should report an error??
- self.report_error("The event name '%s' can not be found." % event)
- # Either way, just let the default handlers grab it.
- return 1
- binding = self._new_binding(handler, HANDLER_ARGS_NATIVE)
- # Cache it.
- self.bindings[event] = binding
-
- handler_args_type = binding.handler_args_type
- # Now actually fire it.
- if handler_args_type == HANDLER_ARGS_GUESS:
- # Can't be native, as natives are never added with "guess".
- # Must be extension or IDLE.
- if event[0] == "<":
- handler_args_type = HANDLER_ARGS_IDLE
- else:
- handler_args_type = HANDLER_ARGS_EXTENSION
- try:
- if handler_args_type == HANDLER_ARGS_EXTENSION:
- args = self.parent_view.idle, event_param
- else:
- args = (event_param,)
- rc = binding.handler(*args)
- if handler_args_type == HANDLER_ARGS_IDLE:
- # Convert to our return code.
- if rc in (None, "break"):
- rc = 0
- else:
- rc = 1
- except:
- message = "Firing event '%s' failed." % event
- print(message)
- traceback.print_exc()
- self.report_error(message)
- rc = 1 # Let any default handlers have a go!
- return rc
-
- def fire_key_event(self, msg):
- key = msg[2]
- keyState = 0
- if win32api.GetKeyState(win32con.VK_CONTROL) & 0x8000:
- keyState = (
- keyState | win32con.RIGHT_CTRL_PRESSED | win32con.LEFT_CTRL_PRESSED
- )
- if win32api.GetKeyState(win32con.VK_SHIFT) & 0x8000:
- keyState = keyState | win32con.SHIFT_PRESSED
- if win32api.GetKeyState(win32con.VK_MENU) & 0x8000:
- keyState = keyState | win32con.LEFT_ALT_PRESSED | win32con.RIGHT_ALT_PRESSED
- keyinfo = key, keyState
- # Special hacks for the dead-char key on non-US keyboards.
- # (XXX - which do not work :-(
- event = self.keymap.get(keyinfo)
- if event is None:
- return 1
- return self.fire(event, None)
|