From: Kevin A. <ka...@us...> - 2004-09-14 17:28:56
|
Update of /cvsroot/pythoncard/PythonCard In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6255 Modified Files: MANIFEST.in model.py widget.py Log Message: added Notebook component added PageBackground class and pageWindow function added testNotebook sample for testing component and class Index: widget.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/widget.py,v retrieving revision 1.132 retrieving revision 1.133 diff -C2 -d -r1.132 -r1.133 *** widget.py 13 May 2004 02:40:23 -0000 1.132 --- widget.py 14 Sep 2004 17:28:45 -0000 1.133 *************** *** 249,254 **** # background.findHandler #background = self.GetParent().GetParent() ! background = wx.GetTopLevelParent(self) if wx.GetApp()._showDebugMenu: --- 249,261 ---- # background.findHandler + # KEA 2004-09-13 + # switching back to the earlier hack for finding the parent background + # in order to support the PageBackground experiments #background = self.GetParent().GetParent() ! parent = self.GetParent() ! if isinstance(parent, wx.Dialog): ! background = parent ! else: ! background = parent.GetParent() if wx.GetApp()._showDebugMenu: *************** *** 392,397 **** # handler could be somewhere else #background = self.GetParent().GetParent() ! background = wx.GetTopLevelParent(self) # this is what is in event.py --- 399,412 ---- # handler could be somewhere else + # KEA 2004-09-13 + # switching back to the earlier hack for finding the parent background + # in order to support the PageBackground experiments #background = self.GetParent().GetParent() ! ## background = wx.GetTopLevelParent(self) ! parent = self.GetParent() ! if isinstance(parent, wx.Dialog): ! background = parent ! else: ! background = parent.GetParent() # this is what is in event.py Index: model.py =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/model.py,v retrieving revision 1.181 retrieving revision 1.182 diff -C2 -d -r1.181 -r1.182 *** model.py 26 Aug 2004 18:36:52 -0000 1.181 --- model.py 14 Sep 2004 17:28:45 -0000 1.182 *************** *** 182,185 **** --- 182,218 ---- + # KEA 2004-09-14 + # this is almost identical to childWindow above + # but in the case of adding a page to a notebook + # the parent is the Notebook component (wx.Notebook control) + # which changes util.main_is_frozen code + + def pageWindow(parent, frameClass, filename=None, rsrc=None): + if filename is None: + if rsrc is None: + if util.main_is_frozen(): + # KEA 2004-05-20 + # running standalone + # need to support py2exe differently than bundlebuilder and mcmillan probably + # but this is the py2exe 0.5 way + # figure out the .rsrc.py filename based on the module name stored in library.zip + filename = os.path.split(sys.modules[frameClass.__module__].__file__)[1] + # parent will be the wx.Notebook + parentFrame = parent.GetParent().GetParent() + filename = os.path.join(parentFrame.application.applicationDirectory, filename) + else: + # figure out the .rsrc.py filename based on the module name + filename = sys.modules[frameClass.__module__].__file__ + # chop the .pyc or .pyo from the end + base, ext = os.path.splitext(filename) + filename = internationalResourceName(base) + rsrc = resource.ResourceFile(filename).getResource() + elif isinstance(rsrc, dict): + rsrc = resource.Resource(rsrc) + else: + rsrc = resource.ResourceFile(filename).getResource() + return frameClass(parent, rsrc.application.backgrounds[0]) + + # KEA 2002-02-25 # custom event for running a pycrustrc.py file *************** *** 1139,1142 **** --- 1172,1767 ---- + PageBackgroundEvents = ( + ## ActivateEvent, + ## CloseEvent, + ## DeactivateEvent, + event.IdleEvent, + ## MaximizeEvent, + ## MinimizeEvent, + ## MoveEvent, + ## RestoreEvent, + ## SizeEvent, + ) + + class PageBackground(Scriptable, wx.Panel, event.EventSource): + """ + A window that contains Widgets. + """ + + def __init__(self, aParent, aBgRsrc): + """ + Initialize this instance. + """ + Scriptable.__init__(self, None) + event.EventSource.__init__(self) + self.id = wx.NewId() + self.resource = aBgRsrc + self.application = wx.GetApp() + self.setName(aBgRsrc.name) + self.setImage(aBgRsrc.image) + self.setTiled(aBgRsrc.tiled) + self.components = WidgetDict(self) + self.menuBar = None + self.statusBar = None + + ## # override for application defined position + ## position = configuration.getOption('defaultBackgroundPosition') + ## if position is None: + ## position = aBgRsrc.position + + ## # KEA 2004-01-18 + ## # have to explicitly declare the close box in wxPython 2.5 + ## style = wx.MINIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX + ## if aBgRsrc.style == ['resizeable']: + ## style = wx.DEFAULT_FRAME_STYLE + # First, call the base class' __init__ method to create the frame + wx.Panel.__init__(self, aParent, + self.id, + ## aBgRsrc.title, + ## position, + size=aBgRsrc.size, + ## wx.NO_FULL_REPAINT_ON_RESIZE, + name=aBgRsrc.name) + + self._initLayout(aBgRsrc.components) + + # KEA 2004-09-14 + # force PageBackground to fit + # space provided by Notebook + self._sizer = wx.BoxSizer(wx.VERTICAL) + self._sizer.Add(self.panel, True, wx.EXPAND) + self._sizer.Fit(self) + self._sizer.SetSizeHints(self) + self.SetSizer(self._sizer) + self.Layout() + + # KEA 2001-08-13 + # can't set the colors until after the panel + # has been created. this initialization should probably work differently + self._setForegroundColor(aBgRsrc.foregroundColor) + self._setBackgroundColor(aBgRsrc.backgroundColor) + + ## self._createMenus(aBgRsrc) + ## self._createStatusBar(aBgRsrc) + + ## # AJT 20.11.2001 + ## # Add icon creation + ## self._setIcon(aBgRsrc) + + ## # 2001-11-08 + ## # hack to preserve the statusbar text + ## if self.statusBar is not None and self.menuBar is not None: + ## wx.EVT_MENU_HIGHLIGHT_ALL(self, self.menuHighlight) + + ## if aParent is None: + ## self.application.SetTopWindow(self) + ## + ## # KEA 2002-04-26 + ## # allow background window to remain hidden + ## if aBgRsrc.visible: + ## self.Show(True) + + # RDS 2004-04-14 + # Post the Background initialization event. + + self.EVT_OPEN_BACKGROUND_TYPE = wx.NewEventType() + self.id = wx.NewId() + self.Connect(self.GetId(), -1, + self.EVT_OPEN_BACKGROUND_TYPE, + self.on_initialize) + #self._dispatchOpenBackground ) + evt = wx.PyCommandEvent(self.EVT_OPEN_BACKGROUND_TYPE, self.GetId()) + evt.target = self + wx.PostEvent(self, evt) + EVT_LATENT_BACKGROUNDBIND(self, self.OnLatentBackgroundBind) + wx.PostEvent(self, wxLatentBackgroundBindEvent()) + # for some reason the Message Watcher isn't a listener yet + # so calling EventLog doesn't do anything + #event.EventLog.getInstance().log('initialize', self.name, True) + + ## self._bindWindowEvents() + + + def on_initialize(self, evt): + # override in subclass + pass + + ## def on_close(self, evt): + ## # override in subclass + ## evt.Skip() + + # KEA 2004-09-14 + # this probably doesn't work, but need to test + # since PageBackground is a wx.Panel + # that contains a wx.Panel + # and it contains a sizer to force it to expand to + # the size of the Notebook set in __init__ above + # I'm not sure if this method makes any sense for PageBackground + def singleItemExpandingSizerLayout(self): + """Convenience method for backgrounds with only a + single component on the background where the component + should expand with the background as in an editor. + + Call from within the on_initialize event handler.""" + + self.sizer = wx.BoxSizer(wx.VERTICAL) + name = self.components.order[0] + self.sizer.Add(self.components[name], True, wx.EXPAND) + self.sizer.Fit(self) + self.sizer.SetSizeHints(self) + self.panel.SetSizer(self.sizer) + self.panel.Layout() + + + # KEA 2004-05-09 + # this is _bindEvents taken from widget.Widget + # so we can see how moving this to Scriptable will impact binding + # comments have been removed + def _bindEvents(self, eventList): + ## background = wx.GetTopLevelParent(self) + background = self + + if wx.GetApp()._showDebugMenu: + bindUnusedEvents = True + else: + bindUnusedEvents = False + + self.boundEvents = {} + + self.eventIdToHandler = {} + self.wxEventIdMap = {} + + if 0: + print "\nBINDING...", self.name + + for eventClass in eventList: + self.wxEventIdMap[eventClass.id] = eventClass + 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: + if not self.boundEvents.get(eventClass.binding, None): + self.Bind(eventClass.binding, self._dispatch) + self.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 self.boundEvents.values(): + print " ", name + print "\n\n" + print "\n self.eventIdToHandler:" + for id in self.eventIdToHandler: + print " ", id, self.eventIdToHandler[id] + print "\n\n" + + # KEA 2004-05-09 + # this is _dispatch taken from widget.Widget + # so we can see how moving this to Scriptable will impact dispatch + # comments have been removed + # the only line I added was self.command = None + # since I'm not sure what we should do about that attribute + # I suspect that the if test should just be changed so that instead of + # if self.command ... + # we use + # if hasattr(self, 'command') and self.command ... + # OOPS one other change + # we're still using unbound methods and after a close event + # additional events will be sent as the frame is closed and destroyed + # in particular the last event appears to be a deactivate event + # to work around this I went ahead and added code + def _dispatch(self, aWxEvent): + # this is a temporary workaround, see comment above + self.command = None + + eventType = aWxEvent.GetEventType() + eventClass = self.wxEventIdMap[eventType] + + eventClassInstance = eventClass() + aWxEvent = eventClassInstance.decorate(aWxEvent, self) + + if self.command and isinstance(eventClassInstance, event.CommandTypeEvent): + eventName = 'command ' + self.command + else: + if isinstance(eventClassInstance, event.InsteadOfTypeEvent): + eventType = eventClassInstance.translateEventType(aWxEvent) + eventName = self.wxEventIdMap[eventType].name + + eventClass = None + eventClassInstance = None + + handler = self.eventIdToHandler.get(eventType, None) + if handler: + event.EventLog.getInstance().log(eventName, self.name, True) + if 0: + print "dispatching", handler.__name__ + aWxEvent.skip = aWxEvent.Skip + + ## background = wx.GetTopLevelParent(self) + background = self + + handler(background, aWxEvent) + + aWxEvent.skip = None + handler = None + background = None + else: + event.EventLog.getInstance().log(eventName, self.name, False) + aWxEvent.Skip() + + aWxEvent.target = aWxEvent.eventObject = None + + def OnLatentBackgroundBind(self, evt): + self._bindEvents(PageBackgroundEvents) + + # KEA 2002-06-27 + # this is a way of loading the shell manually in an app + # if the shell wasn't loaded at startup, so program + # startup is quicker and take up less memory + # if the shell isn't needed + def loadShell(self): + if self.application.shell is None: + self.application.showShell() + + def loadNamespace(self): + self.loadShell() + if self.application.shell is None: + # must have been a problem loading the shell + return + if self.application.namespace is None: + self.application.showNamespace() + + def setName( self, aString ) : + self.name = aString + + def getName( self ) : + return self.name + + def setImage(self, aPath): + self.image = aPath + # Call wxPython + #raise NotImplementedError + + def setTiled(self, aBoolean): + if isinstance(aBoolean, str): + if aBoolean == 'false': + aBoolean = False + else: + aBoolean = True + self.tiled = aBoolean + # Call wxPython + #raise NotImplementedError + + def _getName(self): + return self.name + + def getImage(self): + return self.image + + def getTiled(self): + return self.tiled + + # KEA 2004-03-17 + # the get/set methods above will go away before PythonCard-1.0 + # so that we can just use new-style class properties + + def _getPosition(self): + return self.GetPositionTuple() + + def _setPosition(self, aPosition): + self.SetPosition(aPosition) + + def _getSize(self): + return self.GetSizeTuple() + + def _setSize(self, aSize): + self.SetSize(aSize) + + def _getBackgroundColor(self): + return self.panel.getBackgroundColor() + + def _setBackgroundColor(self, aColor): + self.panel.setBackgroundColor(aColor) + + def _getForegroundColor(self): + return self.panel.getForegroundColor() + + def _setForegroundColor(self, aColor): + self.panel.setForegroundColor(aColor) + + + def enableCommand(self, aString, aBoolean=True): + """ + Fined every component with a 'command' attribute + that matches aString, and enable the component. + """ + self.menuBar.enableCommand(aString, aBoolean) + + for component in self.components.itervalues(): + if component.command == aString: + component.enabled = aBoolean + + def disableCommand(self, aString): + """ + Fined every component with a 'command' attribute + that matches aString, and disable the component. + """ + self.enableCommand(aString, False) + + def _initLayout(self, aResourceList): + """ + Create the gui Widgets for this Background and lay + them out in a Frame. + """ + self.panel = widget.Panel(self, self.image, self.tiled) + + for rsrc in aResourceList: + self.components[rsrc.name] = rsrc + + ## # KEA 2002-05-02 + ## # always create at least a File menu with Quit on the Mac + ## # so we automatically get the Apple menu... + ## def _createMacMenu(self): + ## mnu = wx.Menu() + ## id = wx.NewId() + ## mnu.Append(id, 'E&xit\tAlt+X') + ## + ## menubar = self.GetMenuBar() + ## if menubar is None: + ## menubar = wx.MenuBar() + ## self.SetMenuBar(menubar) + ## menubar.Append(mnu, 'File') + ## wx.EVT_MENU(self, id, self.on_exit_command) + + ## def exit(self): + ## """Exit the application by calling close() + ## on the main application window.""" + ## + ## # regardless of whether this is a child window + ## # or primary window of the application, this should + ## # give us the right window to close to quit the application + ## appWindow = self.application.getCurrentBackground() + ## appWindow.close() + + ## def on_exit_command(self, evt): + ## self.exit() + + ## def _createMenus(self, aResource): + ## # RDS - Only create a menubar if one is defined + ## # in the stack's resource file. + ## # This is a hack, I shouldn't be accessing + ## # the stack resource's __dict)__ directly. + ## if ('menubar' in aResource.__dict__) and (aResource.menubar is not None): + ## self.menuBar = menu.MenuBar(self, aResource.menubar) + ## elif wx.Platform == '__WXMAC__' and self.GetParent() is None: + ## # always create at least a File menu with Quit on the Mac + ## # so we automatically get the Apple menu... + ## # KEA 2004-03-01 + ## # the elif was updated to make sure we only create a menubar + ## # if the background has no parent, aka is the primary app window + ## self._createMacMenu() + ## + ## # KEA and as a further hack, I now add a Debug menu + ## # to the menubar. createMenu will create a menubar + ## # if one doesn't already exist + ## if self.application._showDebugMenu and self.GetParent() == None: + ## self.application._debugMenu = debug.DebugMenu(self.application) + ## self.application._debugMenu.createMenu(self) + ## self.application._debugMenu.bindMenuEvents(self) + + ## # 2001-11-08 + ## # hack to keep the statusbar text from being wiped out + ## def menuHighlight(self, event): + ## self.statusBar.text = self.statusBar.text + ## + ## # KEA 2004-04-14 + ## # subclasses of Background can override this method + ## # if they want to have a different style of statusBar + ## # OnCreateStatusBar is defined for wxFrame + ## # in wxWidgets, but not wxPython, so ignore OnCreateStatusBar + ## # in the wxWidgets docs + ## # need to verify that we don't need a more complex arg list + ## # since that will impact the call in _createStatusBar below + ## # this method is also defined for CustomDialog + ## def createStatusBar(self): + ## return statusbar.StatusBar(self) + ## + ## # KEA 2001-12-25 + ## # method now removes any existing statusbar if the resource + ## # doesn't specify one + ## # this is mostly for the resourceEditor and should have a clearer API + ## def _createStatusBar( self, aResource ) : + ## bar = self.GetStatusBar() + ## if ('statusBar' in aResource.__dict__) and aResource.statusBar: + ## if bar is None: + ## self.statusBar = self.createStatusBar() + ## self.SetStatusBar(self.statusBar) + ## if wx.Platform == '__WXMAC__': + ## #self.statusBar.PositionStatusBar() + ## pass + ## else: + ## if bar is not None: + ## self.SetStatusBar(None) + ## bar.Destroy() + ## # the statusbar changes the window size + ## # so this will for it back + ## #self.SetSize(self.GetSizeTuple()) + ## self.Fit() + ## self.statusBar = None + ## + ## + ## def _setIcon( self, aResource ) : + ## """Set icon based on resource values""" + ## if ('icon' in aResource.__dict__) and (aResource.icon is not None): + ## try: + ## icon = wx.Icon(aResource.icon, wx.BITMAP_TYPE_ICO) + ## self.SetIcon(icon) + ## except: + ## pass + + + ## def _bindWindowEvents(self): + ## wx.EVT_CLOSE(self, self.OnClose) + ## wx.EVT_WINDOW_DESTROY(self, self.OnDestroy) + + ## # KEA 2004-05-09 + ## # this is necessary so that we don't try and dispatch + ## # the activate event which is sent after close + ## # this might not be needed if we start using bound + ## # events, but that will require more testing + ## def OnClose(self, evt): + ## # this will be found when the on_close method above + ## # or override calls close so that we can still + ## # disconnect the deactivateevent during close + ## # otherwise trying to dispatch to + ## self.Disconnect(-1, -1, ActivateEvent.id) + ## evt.Skip() + + ## # KEA 2002-07-09 + ## # make sure wxSTC text, bitmaps, etc. aren't lost + ## # when the app exits + ## def OnDestroy(self, evt): + ## # KEA 2004-04-16 + ## # stopLogging prevents the OleFlushClipboard message + ## # from being displayed at the console when the app quits + ## if self == evt.GetEventObject(): + ## stopLogging = wx.LogNull() + ## wx.TheClipboard.Flush() + ## del stopLogging + ## evt.Skip() + + ## def GetRestoredPosition(self): + ## if self.IsIconized(): + ## return self._restoredPosition + ## else: + ## return self.GetPositionTuple() + + ## def GetRestoredSize(self): + ## if self.IsIconized(): + ## return self._restoredSize + ## else: + ## return self.GetSizeTuple() + + ## def on_minimize(self, evt): + ## #print "minimize", evt.Iconized() + ## #print evt + ## #print evt.GetTimestamp() + ## #print "iconized", evt.Iconized() + ## #print self.GetPositionTuple() + ## #print self.GetSizeTuple() + ## if evt.Iconized() and self.GetPositionTuple() != (-32000, -32000): + ## self._restoredPosition = self.GetPositionTuple() + ## self._restoredSize = self.GetSizeTuple() + ## #print self.restoredPosition, self.restoredSize + ## evt.Skip() + + ## # KEA 2004-04-24 + ## # this doesn't appear to be hooked to an event + ## # did the binding get deleted or did we just + ## # never decide whether we wanted to have a separate + ## # event to denote exiting the app versus calling close + ## # on the main background to quit the app?! + ## def OnExit(self, evt): + ## self.close(True) + + # KEA 2004-04-26 + # why do we need the methods below?! + # what is the use case for them? + # findComponentsByClass has some value + # but any app that needs it can easily do the method itself + # I blew away the same methods in CustomDialog + # getComponent, getComponents, findAllComponents, findComponentsByClass + + # RDS = new API + def getComponent( self, path ) : + return eval( 'self.components.' + path ) + + # RDS - new API + def getComponents( self ) : + return self.findAllComponents() + + # RDS - deprecated + def findAllComponents( self ) : + """ + Return a copy of the list of Components in this + Background. We're not just returning + self.components.values because we don't want + someone to inadvertently whack the internal list + of Components. + """ + components = [] + for component in self.components.itervalues() : + components.append( component ) + return components + + def findComponentsByClass( self, aComponentClass ) : + """ + Return a list of Component's that are instances + of the specified Component class. + """ + components = [] + for component in self.components.itervalues() : + if isinstance( component, aComponentClass ) : + components.append( component ) + return components + + # KEA 2001-07-31 + # we may want to put this someplace else, but we do need access + # to the componenet list + def findFocus(self): + # the wxPython widget that has focus + widgetWX = wx.Window_FindFocus() + if widgetWX is None: + return None + else: + for widget in self.components.itervalues(): + if widgetWX == widget: + return widget + # is this even possible? focus in another window maybe? + return None + + ## # KEA 2004-03-17 + ## # mixedCase aliases + ## close = wx.Frame.Close + ## getParent = wx.Frame.GetParent + + # KEA 2004-03-17 + # define Python 2.2 new-style class properties + backgroundColor = property(_getBackgroundColor, _setBackgroundColor, doc="backgroundColor of the background") + foregroundColor = property(_getForegroundColor, _setForegroundColor, doc="foregroundColor of the background") + position = property(_getPosition, _setPosition, doc="position of the background") + size = property(_getSize, _setSize, doc="size of the background") + ## title = property(wx.Frame.GetTitle, wx.Frame.SetTitle) + visible = property(wx.Frame.IsShown, wx.Frame.Show, doc="whether the background window is visible") + + class CustomDialog( Scriptable, wx.Dialog, event.EventSource): """The dialog class used by all custom dialogs.""" Index: MANIFEST.in =================================================================== RCS file: /cvsroot/pythoncard/PythonCard/MANIFEST.in,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** MANIFEST.in 18 Aug 2004 22:18:49 -0000 1.15 --- MANIFEST.in 14 Sep 2004 17:28:45 -0000 1.16 *************** *** 9,12 **** --- 9,13 ---- prune samples/counter prune samples/fpop + prune samples/testNotebook exclude docs/html/linux_installation.html exclude docs/html/macosx_installation.html |