|
From: Kevin A. <ka...@us...> - 2004-05-02 19:50:08
|
Update of /cvsroot/pythoncard/PythonCard In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21950 Modified Files: event.py widget.py Log Message: moved _binding and _dispatch into widget.py added component specific _binding to TextField, TextArea, PasswordField switched to wx.GetApp and wx.GetTopLevelwindow added binding and id attributes to background event classes added TextArea to testevents Index: widget.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/widget.py,v retrieving revision 1.119 retrieving revision 1.120 diff -C2 -d -r1.119 -r1.120 *** widget.py 28 Apr 2004 01:24:50 -0000 1.119 --- widget.py 2 May 2004 19:49:57 -0000 1.120 *************** *** 224,227 **** --- 224,465 ---- visible = property(_getVisible, _setVisible) + # KEA 2004-05-02 + # this will probably end up in Scriptable or Component + # it should be completely generic + # the only problem part would be the reference to the parent (background) + # where the events are actually defined which would make this problematic + # for a compound component or events bound to a Panel + # what we really want is a reference to the application instance + # there is probably some method to give us that in wxWidgets + # UPDATE - I think GetTopLevelParent is what I was looking for + def _bindEvents(self, eventList): + # shouldn't components be subclasses of Scriptable? + # components would have their own handlers but when + # looking for a handler match it will search the parents + # for now just grab handlers from the background + + # the references below would be self.findHandler instead of + # background.findHandler + + #background = self.GetParent().GetParent() + background = wx.GetTopLevelParent(self) + + # where should this check go? + # should we just set a "global" in the app instance such as + # self.stack.app.bindUnusedEvents + # this kind of thing isn't going to work for Rowland's compound + # components + if wx.GetApp()._showDebugMenu: + bindUnusedEvents = True + else: + bindUnusedEvents = False + + # helper variable to simplify test for whether to bind InsteadOfTypeEvents + boundEvents = {} + + self.eventIdToHandler = {} + self.wxEventIdMap = {} + + if 0: + print "\nBINDING...", self.name + + for eventClass in eventList: + #for eventClass in ButtonEvents: + # need to figure out a way to avoid the need + # for this id to class mapping which is used in _dispatch below + self.wxEventIdMap[eventClass.id] = eventClass + # command handler overrides normal mouseClick or select handler + # so dispatch will automatically dispatch to the command handler + # by looking up the handler this way + # it also means that if there is a command association with this component + # then the regular mouseClick or select handler will never be bound, just ignored + if issubclass(eventClass, event.CommandTypeEvent) and self.command: + handler = background.findHandler('on_' + self.command + '_command') + if not handler: + handler = background.findHandler('on_' + self.name + '_' + eventClass.name) + else: + handler = background.findHandler('on_' + self.name + '_' + eventClass.name) + if not handler: + handler = background.findHandler('on_' + eventClass.name) + if handler or bindUnusedEvents: + # only bind events that have an event handler + # in this scenario unused events are never bound + # which is more efficient, but the Message Watcher needs + # to be changed + # alternatively we can bind everything and then in _dispatch + # if there isn't a match in eventIdToHandler then we know + # the event isn't used and we can set used to False + # the complication would be that we probably have to have to + # always call Skip() which may or may not be a hassle with components + + # this doesn't bind command events + # they would be of the form on_somename_command + # or perhaps on_command but I don't think we would want + # to support that + # the event binding would be specific to a component + # since on dispatch command overrides something like mouseClickEvent + # but the name of the command is not related to the component + # need to look at whether self.command has a value and then bind + # with ButtonMouseClickEvent.binding if that isn't already bound + # then in dispatch have to check again I think + + # need to avoid double binding + # also binding shouldn't be order-specific + # so how to avoid binding mouseDrag to _dispatch + # if mouseMove is already bound or if binding mouseMove + # not rebinding if mouseDrag is already bound + # perhaps MouseDragEvent keeps a reference to MouseMoveEvent + # and that is inserted into boundEvents, then we check boundEvents + # prior to rebinding? + if not boundEvents.get(eventClass.binding, None): + self.Bind(eventClass.binding, self._dispatch) + boundEvents[eventClass.binding] = eventClass.name + if handler: + if 0: + print " binding", self.name, eventClass.name, handler._name, eventClass.id + self.eventIdToHandler[eventClass.id] = handler + + if 0: + print "\n boundEvents:" + for name in boundEvents.values(): + print " ", name + print "\n\n" + print "\n self.eventIdToHandler:" + for id in self.eventIdToHandler: + print " ", id, self.eventIdToHandler[id]._function + print "\n\n" + # there is a good chance we will need to know + # which events are bound, if we want to dynamically add or remove + # events later, so go ahead and keep a reference to the list + self.boundEvents = boundEvents + + def _dispatch(self, aWxEvent): + eventType = aWxEvent.GetEventType() + + eventName = None + + if eventType == wx.wxEVT_TIMER: + aWxEvent.interval = aWxEvent.GetInterval() + # wxPython 2.5.1.5 workaround + # for some reason wx.TimerEvent does not contain the event target + # so we have to set it ourselves + aWxEvent.target = aWxEvent.eventObject = self + else: + try: + # all events should have GetEventObject() + # except of course for wx.TimerEvent above + # KEA 2004-04-25 + # should we remove this redundant identifier? + aWxEvent.target = aWxEvent.eventObject = self + except: + pass + # Each of these could check the event class like + # wxListEvent and wxTreeEvent above. + try: + # mouse and key events + aWxEvent.position = tuple(aWxEvent.GetPosition()) + aWxEvent.x = aWxEvent.GetX() + aWxEvent.y = aWxEvent.GetY() + aWxEvent.altDown = aWxEvent.AltDown() + aWxEvent.controlDown = aWxEvent.ControlDown() + aWxEvent.shiftDown = aWxEvent.ShiftDown() + except: + pass + try: + # key events + aWxEvent.keyCode = aWxEvent.GetKeyCode() + except: + pass + if issubclass(self.wxEventIdMap[eventType], event.CommandTypeEvent): + # could be command, so need to report the name + # for the handler if it exists + if self.command: + eventName = 'command' + elif eventType == event.MouseMoveEvent.id: + # check to see if this is a mouseDrag + if aWxEvent.Dragging(): + eventType = event.MouseDragEvent.id + # don't need this if all event types have unique ids + #eventName = event.MouseDragEvent.name + + # the component-specific helper attributes below + # should be handled in the relevant component _dispatch + # not the generic one + """ + if eventType in [wx.wxEVT_COMMAND_LIST_KEY_DOWN, + wx.wxEVT_COMMAND_TREE_KEY_DOWN]: + try: + # key events are different for wxTreeCtrl and wxListCtrl + aWxEvent.keyCode = aWxEvent.GetCode() + except: + pass + try: + # wxListEvent doesn't have GetKeyEvent for some reason + keyEvent = aWxEvent.GetKeyEvent() + aWxEvent.altDown = keyEvent.AltDown() + aWxEvent.controlDown = keyEvent.ControlDown() + aWxEvent.shiftDown = keyEvent.ShiftDown() + except: + pass + elif eventType in [wx.wxEVT_COMMAND_TREE_BEGIN_DRAG, \ + wx.wxEVT_COMMAND_TREE_BEGIN_RDRAG, \ + wx.wxEVT_COMMAND_TREE_END_DRAG, \ + wx.wxEVT_COMMAND_LIST_BEGIN_DRAG, \ + wx.wxEVT_COMMAND_LIST_BEGIN_RDRAG, \ + wx.wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, \ + wx.wxEVT_COMMAND_LIST_COL_DRAGGING, \ + wx.wxEVT_COMMAND_LIST_COL_END_DRAG]: + try: + # The mouse position during a drag event + # there doesn't appear to be a way of getting the + # state of the shift, alt, and control keys + # during a mouse drag. + aWxEvent.position = tuple(aWxEvent.GetPoint()) + aWxEvent.x = aWxEvent.position[0] + aWxEvent.y = aWxEvent.position[1] + except: + pass + """ + + if not eventName: + eventName = self.wxEventIdMap[eventType].name + + # it shouldn't be possible to be in _dispatch for an event + # that wasn't bound above, but just in case... + handler = self.eventIdToHandler.get(eventType, None) + if handler: + event.EventLog.getInstance().log(eventName, self.name, True) + if 0: + print "dispatching", handler._name + # make a lowercase alias + aWxEvent.skip = aWxEvent.Skip + + # the event handlers are part of the Background so + # we have to have a reference to call the handler below + + # if Scriptable takes over the dispatch then + # this would need to work differently if the actual + # handler could be somewhere else + + #background = self.GetParent().GetParent() + background = wx.GetTopLevelParent(self) + + # this is what is in event.py + # aHandler.getFunction()( aOwner, self.getSource(), self ) + handler.getFunction()(background, aWxEvent) + + # do we have to clean up this alias? + aWxEvent.skip = None + # how about this local reference to handler? + handler = None + background = None + else: + event.EventLog.getInstance().log(eventName, self.name, False) + # hopefully this is all we need to do for "unused events" + aWxEvent.Skip() + + # cleanup + aWxEvent.target = aWxEvent.eventObject = None + class Panel(wx.Panel): Index: event.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/event.py,v retrieving revision 1.62 retrieving revision 1.63 diff -C2 -d -r1.62 -r1.63 *** event.py 2 May 2004 16:31:33 -0000 1.62 --- event.py 2 May 2004 19:49:56 -0000 1.63 *************** *** 403,436 **** class MoveEvent(Event): name = 'move' class SizeEvent(Event): name = 'size' class CloseEvent(Event): name = 'close' class MinimizeEvent(Event): name = 'minimize' ! class RestoreEvent(Event): name = 'restore' class MaximizeEvent(Event): name = 'maximize' class ActivateEvent(Event): name = 'activate' ! class DeactivateEvent(Event): name = 'deactivate' class IdleEvent(Event): name = 'idle' --- 403,454 ---- class MoveEvent(Event): name = 'move' + binding = wx.EVT_MOVE + id = wx.wxEVT_MOVE class SizeEvent(Event): name = 'size' + binding = wx.EVT_SIZE + id = wx.wxEVT_SIZE class CloseEvent(Event): name = 'close' + binding = wx.EVT_CLOSE + id = wx.wxEVT_CLOSE_WINDOW class MinimizeEvent(Event): name = 'minimize' + binding = wx.EVT_ICONIZE + id = wx.wxEVT_ICONIZE ! class RestoreEvent(Event, InsteadOfTypeEvent): name = 'restore' + binding = wx.EVT_ICONIZE + id = wx.NewEventType() class MaximizeEvent(Event): name = 'maximize' + binding = wx.EVT_MAXIMIZE + id = wx.wxEVT_MAXIMIZE class ActivateEvent(Event): name = 'activate' + binding = wx.EVT_ACTIVATE + id = wx.wxEVT_ACTIVATE ! class DeactivateEvent(Event, InsteadOfTypeEvent): name = 'deactivate' + binding = wx.EVT_ACTIVATE + id = wx.NewEventType() class IdleEvent(Event): name = 'idle' + binding = wx.EVT_IDLE + id = wx.wxEVT_IDLE |