class ZNavigatorView(ZBoxedView, IZAccountStoreListener, IZDocumentIndexListener): def __init__(self, parent): self.indexEventQueue = Queue() self.accountEventQueue = Queue() self.model = None ZBoxedView.__init__(self, parent) self.treeView.refresh() self._restoreTreeSelection() # end __init__() def getViewId(self): return IZViewIds.NAVIGATOR_VIEW # end getViewId() def _getHeaderBitmap(self): return getResourceRegistry().getBitmap(u"images/perspectives/standard/navigator/navigator.png") #$NON-NLS-1$ # end _getHeaderBitmap() def _getHeaderLabel(self): return _extstr(u"navigator.AccountNavigator") #$NON-NLS-1$ # end _getHeaderLabel() def _createHeaderWidgets(self, parent, widgetList): # Register for events before creating the model so that we don't miss any. # Register for events after init'ing WX! self._registerAsListener() self.model = ZNavigatorModel() # Collapse All button bitmap = getResourceRegistry().getBitmap(u"images/perspectives/standard/navigator/collapseAll.png") #$NON-NLS-1$ self.collapseAllButton = ZImageButton(parent, bitmap, False, None, True) self.collapseAllButton.SetToolTipString(_extstr(u"navigator.CollapseAllTooltip")) #$NON-NLS-1$ # Dashboard button bitmap = getResourceRegistry().getBitmap(u"images/perspectives/standard/dashboard.png") #$NON-NLS-1$ self.dashboardButton = ZImageButton(parent, bitmap, False, None, True) self.dashboardButton.SetToolTipString(_extstr(u"navigator.DashboardTooltip")) #$NON-NLS-1$ widgetList.append(self.collapseAllButton) widgetList.append(self.dashboardButton) # end _createHeaderWidgets() def _createContentWidgets(self, parent): self.treeImageList = self._createTreeImageList() self.treeProvider = ZTreeNodeBasedContentProvider(self.model.getNavigatorTreeRoot(), self.treeImageList) treeStyle = wx.NO_BORDER | wx.TR_HIDE_ROOT | wx.TR_LINES_AT_ROOT | wx.TR_SINGLE | wx.TR_HAS_BUTTONS self.treeView = ZTreeView(self.treeProvider, parent, style = treeStyle) dropTarget = ZNavigatorViewDropTarget(self.treeView, self) self.treeView.SetDropTarget(dropTarget) # end _createContentWidgets() def _layoutContentWidgets(self): box = wx.BoxSizer(wx.VERTICAL) box.Add(self.treeView, 1, wx.EXPAND) return box # end _layoutContentWidgets() def _createTreeImageList(self): registry = getResourceRegistry() imgList = ZMappedImageList() for img in [u"unpublished", u"account", u"blog", u"posts", u"links", u"images", u"tags"]: #$NON-NLS-1$ #$NON-NLS-2$ #$NON-NLS-3$ #$NON-NLS-4$ #$NON-NLS-5$ #$NON-NLS-6$ #$NON-NLS-7$ #$NON-NLS-8$ imgList.addImage(img, registry.getBitmap(u"images/perspectives/standard/navigator/%s.png" % img)) #$NON-NLS-1$ return imgList # end _createTreeImageList() def _bindWidgetEvents(self): ZBoxedView._bindWidgetEvents(self) self.Bind(wx.EVT_TREE_SEL_CHANGED, self.onSelectionChanged, self.treeView) self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.onItemRightClick, self.treeView) self.Bind(wx.EVT_BUTTON, self.onDashboardButton, self.dashboardButton) self.Bind(wx.EVT_BUTTON, self.onCollapseAllButton, self.collapseAllButton) self.Bind(ZEVT_REFRESH, self.onZoundryRefresh, self) wx.EVT_SET_FOCUS(self.treeView, self.onFocus) wx.EVT_KILL_FOCUS(self.treeView, self.onUnFocus) # end _bindWidgetEvents() def onFocus(self, event): selection = self._getCurrentSelection() if selection: fireViewSelectionEvent(selection, self) event.Skip() # end onFocus() def onUnFocus(self, event): selection = self._getCurrentSelection() if selection: fireViewUnselectionEvent() event.Skip() # end onUnFocus() def onDashboardButton(self, event): self.treeView.UnselectAll() fireViewSelectionEvent(ZViewSelection(IZViewSelectionTypes.UNPUBLISHED_ACCOUNT_SELECTION, None), self) event.Skip() # end onDashboardButton() def onCollapseAllButton(self, event): self.treeView.UnselectAll() self.treeView.collapseAll() fireViewSelectionEvent(ZViewSelection(IZViewSelectionTypes.UNPUBLISHED_ACCOUNT_SELECTION, None), self) event.Skip() # end onCollapseAllButton() def onItemRightClick(self, event): itemId = event.GetItem() node = self.treeView.GetPyData(itemId) nodeType = node.getType() if nodeType == NODE_TYPE_ACCOUNT: account = node.getAccount() menu = self._createAccountCtxMenu(account) self.PopupMenu(menu) menu.Destroy() if nodeType == NODE_TYPE_BLOG: blog = node.getBlog() menu = self._createBlogCtxMenu(blog) self.PopupMenu(menu) menu.Destroy() event.Skip() # end onItemRightClick() def _createAccountCtxMenu(self, account): menuContext = ZAccountMenuActionContext(self, account) menuModel = ZBlogAccountMenuModel() provider = ZModelBasedMenuContentProvider(menuModel, menuContext) eventHandler = ZModelBasedMenuEventHandler(menuModel, menuContext) return ZMenu(self, menuModel.getRootNode(), provider, eventHandler) # end _createAccountCtxMenu() def _createBlogCtxMenu(self, blog): menuContext = ZBlogMenuActionContext(self, blog) menuModel = ZBlogMenuModel() provider = ZModelBasedMenuContentProvider(menuModel, menuContext) eventHandler = ZModelBasedMenuEventHandler(menuModel, menuContext) return ZMenu(self, menuModel.getRootNode(), provider, eventHandler) # end _createBlogCtxMenu() def onSelectionChanged(self, event): selection = self._getCurrentSelection() if selection: fireViewSelectionEvent(selection, self) else: fireViewUnselectionEvent() event.Skip() # end _onSelectionChanged() def onAccountAdded(self, account): self.accountEventQueue.put( (ACCOUNT_EVENT_ADD, account) ) self.model.addAccount(account) fireRefreshEvent(self) # end onAccountAdded() def onAccountChanged(self, account): self.accountEventQueue.put( (ACCOUNT_EVENT_UPDATE, account) ) self.model.updateAccount(account) fireRefreshEvent(self) # end onAccountChange() def onAccountDeleted(self, account): self.accountEventQueue.put( (ACCOUNT_EVENT_DELETE, account) ) self.model.removeAccount(account) fireRefreshEvent(self) # end onAccountDeleted() def onIndexChange(self, event): shouldRefresh = event.getEventType() == IZDocIndexEvent.DOCINDEX_EVENTTYPE_ADD or \ event.getEventType() == IZDocIndexEvent.DOCINDEX_EVENTTYPE_REMOVE if shouldRefresh: self.indexEventQueue.put(event) fireRefreshEvent(self) # end onIndexChange() def onBlogEntryDropped(self, blogId, node): getLoggerService().debug(u"Dropped blog entry '%s' onto blog node '%s'." % (blogId, node.getBlog().getId())) #$NON-NLS-1$ ZShowNotYetImplementedMessage(self) # end onBlogEntryDropped() def onZoundryRefresh(self, event): #@UnusedVariable nodesToRefresh = self._getNodesToRefresh() self.treeView.refresh(nodesToRefresh) # end onZoundryRefresh() # Gets the list of nodes to refresh based on the current queue of index events. def _getNodesToRefresh(self): nodesToRefresh = [] # If there are any account events, refresh the whole tree if not self.accountEventQueue.empty(): # Clear out the account event queue while not self.accountEventQueue.empty(): self.accountEventQueue.get() return None # If there are index events, then we can refresh only parts of the tree while not self.indexEventQueue.empty(): event = self.indexEventQueue.get() dirtyNodes = None if event.getEventType() == IZDocIndexEvent.DOCINDEX_EVENTTYPE_ADD: if event.getDataType() == IZDocIndexEvent.DOCINDEX_DATATYPE_DOCUMENT: dirtyNodes = self.model.addDocumentIDO(event.getDocumentIDO()) elif event.getDataType() == IZDocIndexEvent.DOCINDEX_DATATYPE_IMAGE: dirtyNodes = self.model.addImageIDO(event.getImageIDO()) elif event.getDataType() == IZDocIndexEvent.DOCINDEX_DATATYPE_LINK: dirtyNodes = self.model.addLinkIDO(event.getLinkIDO()) elif event.getDataType() == IZDocIndexEvent.DOCINDEX_DATATYPE_TAG: dirtyNodes = self.model.addTagIDO(event.getTagIDO()) elif event.getEventType() == IZDocIndexEvent.DOCINDEX_EVENTTYPE_REMOVE: if event.getDataType() == IZDocIndexEvent.DOCINDEX_DATATYPE_DOCUMENT: dirtyNodes = self.model.removeDocumentIDO(event.getDocumentIDO()) elif event.getDataType() == IZDocIndexEvent.DOCINDEX_DATATYPE_IMAGE: dirtyNodes = self.model.removeImageIDO(event.getImageIDO()) elif event.getDataType() == IZDocIndexEvent.DOCINDEX_DATATYPE_LINK: dirtyNodes = self.model.removeLinkIDO(event.getLinkIDO()) elif event.getDataType() == IZDocIndexEvent.DOCINDEX_DATATYPE_TAG: dirtyNodes = self.model.removeTagIDO(event.getTagIDO()) if dirtyNodes is not None: nodesToRefresh.extend(dirtyNodes) return nodesToRefresh # end _getNodesToRefresh() def _getCurrentSelection(self): treeIDs = self.treeView.GetSelections() nodes = map(self.treeView.GetPyData, treeIDs) # Just return the 1st node - currently multi-selection is disabled. for node in nodes: return createViewSelection(node) return None # end _getCurrentSelection() def destroy(self): self._saveTreeLayout() self._unregisterAsListener() # end destroy() def _saveTreeLayout(self): visitor = ZTreeLayoutSaveVisitor() self.treeView.accept(visitor) self._saveTreeSelection() # Save the properties getApplicationModel().getUserProfile().getProperties().save() # end _saveTreeLayout() def _saveTreeSelection(self): nodes = self.treeView.getSelectedNodes() hashValue = 0 if nodes: node = nodes[0] hashValue = node.hashCode() userPrefs = getApplicationModel().getUserProfile().getPreferences() userPrefs.setUserPreference(IZBlogAppUserPrefsKeys.NAVIGATOR_VIEW_SELECTION, unicode(hashValue)) # end _saveTreeSelection() def _restoreTreeSelection(self): userPrefs = getApplicationModel().getUserProfile().getPreferences() hashValue = userPrefs.getUserPreferenceInt(IZBlogAppUserPrefsKeys.NAVIGATOR_VIEW_SELECTION, 0) if hashValue != 0: visitor = ZTreeSelectionRestoreVisitor(self, hashValue) self.treeView.accept(visitor) # end _restoreTreeSelection() def _registerAsListener(self): self._registerAsAccountListener() self._registerAsIndexListener() # end _registerAsListener() def _unregisterAsListener(self): self._unregisterAsAccountListener() self._unregisterAsIndexListener() # end _unregisterAsListener() def _registerAsAccountListener(self): engine = getApplicationModel().getEngine() accountStore = engine.getService(IZBlogAppServiceIDs.ACCOUNT_STORE_SERVICE_ID) accountStore.addListener(self) # end _registerAsAccountListener() def _unregisterAsAccountListener(self): engine = getApplicationModel().getEngine() accountStore = engine.getService(IZBlogAppServiceIDs.ACCOUNT_STORE_SERVICE_ID) accountStore.removeListener(self) # end _unregisterAsAccountListener() def _registerAsIndexListener(self): engine = getApplicationModel().getEngine() accountStore = engine.getService(IZBlogAppServiceIDs.DOCUMENT_INDEX_SERVICE_ID) accountStore.addListener(self) # end _registerAsIndexListener() def _unregisterAsIndexListener(self): engine = getApplicationModel().getEngine() accountStore = engine.getService(IZBlogAppServiceIDs.DOCUMENT_INDEX_SERVICE_ID) accountStore.removeListener(self)
class ZLinksView(ZBoxedView, IZDocumentIndexListener): def __init__(self, parent): self.link = None self.blog = None self.indexService = getApplicationModel().getService( IZBlogAppServiceIDs.DOCUMENT_INDEX_SERVICE_ID) self.accountStore = getApplicationModel().getService( IZBlogAppServiceIDs.ACCOUNT_STORE_SERVICE_ID) self.model = ZContextInfoLinksModel(ZLinkSearchFilter()) self.openLinkAction = getApplicationModel().getActionRegistry( ).findAction(IZAppActionIDs.OPEN_LINK_ACTION) ZBoxedView.__init__(self, parent) self._registerAsIndexListener() self.validSelection = False # end __init__() def getViewId(self): return IZViewIds.LINKS_LIST_VIEW # end getViewId() def _getHeaderBitmap(self): return getResourceRegistry().getBitmap( u"images/perspectives/standard/links.png") #$NON-NLS-1$ # end _getHeaderBitmap() def _getHeaderLabel(self): return _extstr(u"linksview.Links") #$NON-NLS-1$ # end _getHeaderLabel() def _createHeaderWidgets(self, parent, widgetList): choices = self._getSearchBoxChoices() bitmap = getResourceRegistry().getBitmap( u"images/perspectives/standard/contextinfo/linksview/search.png" ) #$NON-NLS-1$ self.searchTextBox = ZAdvancedTextBox(parent, bitmap, choices, False) self.searchTextBox.setCurrentChoice(SEARCH_HOST) self.searchTextBox.SetSizeHints(220, -1) widgetList.append(self.searchTextBox) # end _createHeaderWidgets() def _createContentWidgets(self, parent): treeStyle = wx.TR_HIDE_ROOT | wx.TR_LINES_AT_ROOT | wx.TR_SINGLE | wx.TR_HAS_BUTTONS | wx.NO_BORDER provider = ZLinkTreeContentProvider(self.model) self.linksTreeView = ZTreeView(provider, parent, style=treeStyle) # end _createContentWidgets() def _layoutContentWidgets(self): box = wx.BoxSizer(wx.VERTICAL) box.Add(self.linksTreeView, 1, wx.EXPAND) return box # end _layoutContentWidgets() def _bindWidgetEvents(self): ZBoxedView._bindWidgetEvents(self) self.Bind(ZEVT_REFRESH, self.onZoundryRefresh, self) self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.onLinkActivated, self.linksTreeView) self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.onLinkRightClick, self.linksTreeView) self.Bind(wx.EVT_TREE_SEL_CHANGED, self.onLinkSelected, self.linksTreeView) # self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.onEntryBeginDrag, self.linksTreeView) self.Bind(wx.EVT_TEXT_ENTER, self.onSearchText, self.searchTextBox) self.Bind(ZEVT_VIEW_SELECTION_CHANGED, self.onViewSelectionChanged) wx.EVT_SET_FOCUS(self.linksTreeView, self.onFocus) wx.EVT_KILL_FOCUS(self.linksTreeView, self.onUnFocus) # end _bindWidgetEvents() def refreshContent(self, selection): (accountId, blogId) = selection.getData() filter = ZLinkSearchFilter() if blogId is not None: account = self.accountStore.getAccountById(accountId) self.blog = account.getBlogById(blogId) filter.setAccountIdCriteria(accountId) filter.setBlogIdCriteria(blogId) else: self.blog = None filter.setAccountIdCriteria( IZLinkSearchFilter.UNPUBLISHED_ACCOUNT_ID) filter.setBlogIdCriteria(IZLinkSearchFilter.UNPUBLISHED_BLOG_ID) self.model = ZContextInfoLinksModel(filter) self.linksTreeView.setContentProvider( ZLinkTreeContentProvider(self.model)) self.linksTreeView.refresh() self.linksTreeView.deselectAll() self.onInvalidSelection() fireViewUnselectionEvent() # end refreshContent() def onViewSelectionChanged(self, event): if event.getSelection().getType( ) == IZViewSelectionTypes.BLOG_LINKS_SELECTION: self.refreshContent(event.getSelection()) # end onViewSelectionChanged() def onFocus(self, event): if self.link: fireViewSelectionEvent(ZLinkSelection(self.link, self.blog), self) else: fireViewUnselectionEvent() event.Skip() # end onFocus() def onUnFocus(self, event): fireViewUnselectionEvent() event.Skip() # end onUnFocus() def onSearchText(self, event): self.model.setHostCriteria(event.GetString()) self.model.refresh() self.linksTreeView.clear() self.linksTreeView.refresh() self.linksTreeView.deselectAll() self.onInvalidSelection() fireViewEvent(ZViewEvent(VIEWLINKSFILTERCHANGEDEVENT, self)) event.Skip() # end onSearchText() # # def onEntryBeginDrag(self, event): # index = event.GetIndex() # docIDO = self.model.getEntry(index) # docId = docIDO.getId() # # # FIXME also add some sort of custom format for dragging to the Explorer/TextPad (use a composite data object) # data = ZBlogPostDataObjectInternal(docId) # dragSource = wx.DropSource(self) # dragSource.SetData(data) # dragSource.DoDragDrop(wx.Drag_CopyOnly) # event.Skip() # # end onEntryBeginDrag() def _updateModel(self, refreshData): (eventType, linkIDO) = refreshData shouldRefresh = False if eventType == IZDocIndexEvent.DOCINDEX_EVENTTYPE_ADD: shouldRefresh = self.model.addLink(linkIDO) elif eventType == IZDocIndexEvent.DOCINDEX_EVENTTYPE_REMOVE: shouldRefresh = self.model.removeLink(linkIDO) elif eventType == IZDocIndexEvent.DOCINDEX_EVENTTYPE_UPDATE: shouldRefresh = self.model.updateLink(linkIDO) return shouldRefresh # end _updateModel() # This is the only method that can happen on a non-UI thread. It will # gather up the needed data, then fire a "refresh ui" event. That event # will get picked up by the UI thread and the view will refresh. def onIndexChange(self, event): if event.getDataType() == IZDocIndexEvent.DOCINDEX_DATATYPE_LINK: refreshData = (event.getEventType(), event.getLinkIDO()) fireRefreshEvent(self, refreshData) # end onIndexChange() def onZoundryRefresh(self, event): if self._updateModel(event.getData()): self.linksTreeView.refresh() event.Skip() # end onZoundryRefresh() def onLinkActivated(self, event): node = self.linksTreeView.GetPyData(event.GetItem()) if isinstance(node, ZLinkIDONode): link = node.getLinkIDO() context = ZLinkIDOActionContext(self, link) self.openLinkAction.runAction(context) event.Skip # end onLinkActivated() def onLinkRightClick(self, event): node = self.linksTreeView.GetPyData(event.GetItem()) if isinstance(node, ZLinkIDONode): link = node.getLinkIDO() context = ZLinkIDOActionContext(self, link) menuModel = ZLinkMenuModel() menu = ZModelBasedMenu(menuModel, context, self) self.PopupMenu(menu) menu.Destroy() event.Skip() # end onLinkRightClick() def onLinkSelected(self, event): node = self.linksTreeView.GetPyData(event.GetItem()) if isinstance(node, ZLinkIDONode): self.link = node.getLinkIDO() if self.link: fireViewSelectionEvent(ZLinkSelection(self.link, self.blog), self) else: fireViewUnselectionEvent() event.Skip() # end onLinkSelected() def onInvalidSelection(self): self.link = None # end onInvalidSelection() def destroy(self): self._unregisterAsIndexListener() # end destroy() def _registerAsIndexListener(self): self.indexService.addListener(self) # end _registerAsIndexListener() def _unregisterAsIndexListener(self): self.indexService.removeListener(self) # end _unregisterAsIndexListener() def _getSearchBoxChoices(self): return [ (u"Host", None, SEARCH_HOST), #$NON-NLS-1$ ]
class ZNavigatorView(ZBoxedView, IZAccountStoreListener, IZDocumentIndexListener): def __init__(self, parent): self.indexEventQueue = Queue() self.accountEventQueue = Queue() self.model = None ZBoxedView.__init__(self, parent) self.treeView.refresh() self._restoreTreeSelection() # end __init__() def getViewId(self): return IZViewIds.NAVIGATOR_VIEW # end getViewId() def _getHeaderBitmap(self): return getResourceRegistry().getBitmap( u"images/perspectives/standard/navigator/navigator.png" ) #$NON-NLS-1$ # end _getHeaderBitmap() def _getHeaderLabel(self): return _extstr(u"navigator.AccountNavigator") #$NON-NLS-1$ # end _getHeaderLabel() def _createHeaderWidgets(self, parent, widgetList): # Register for events before creating the model so that we don't miss any. # Register for events after init'ing WX! self._registerAsListener() self.model = ZNavigatorModel() # Collapse All button bitmap = getResourceRegistry().getBitmap( u"images/perspectives/standard/navigator/collapseAll.png" ) #$NON-NLS-1$ self.collapseAllButton = ZImageButton(parent, bitmap, False, None, True) self.collapseAllButton.SetToolTipString( _extstr(u"navigator.CollapseAllTooltip")) #$NON-NLS-1$ # Dashboard button bitmap = getResourceRegistry().getBitmap( u"images/perspectives/standard/dashboard.png") #$NON-NLS-1$ self.dashboardButton = ZImageButton(parent, bitmap, False, None, True) self.dashboardButton.SetToolTipString( _extstr(u"navigator.DashboardTooltip")) #$NON-NLS-1$ widgetList.append(self.collapseAllButton) widgetList.append(self.dashboardButton) # end _createHeaderWidgets() def _createContentWidgets(self, parent): self.treeImageList = self._createTreeImageList() self.treeProvider = ZTreeNodeBasedContentProvider( self.model.getNavigatorTreeRoot(), self.treeImageList) treeStyle = wx.NO_BORDER | wx.TR_HIDE_ROOT | wx.TR_LINES_AT_ROOT | wx.TR_SINGLE | wx.TR_HAS_BUTTONS self.treeView = ZTreeView(self.treeProvider, parent, style=treeStyle) dropTarget = ZNavigatorViewDropTarget(self.treeView, self) self.treeView.SetDropTarget(dropTarget) # end _createContentWidgets() def _layoutContentWidgets(self): box = wx.BoxSizer(wx.VERTICAL) box.Add(self.treeView, 1, wx.EXPAND) return box # end _layoutContentWidgets() def _createTreeImageList(self): registry = getResourceRegistry() imgList = ZMappedImageList() for img in [ u"unpublished", u"account", u"blog", u"posts", u"links", u"images", u"tags" ]: #$NON-NLS-1$ #$NON-NLS-2$ #$NON-NLS-3$ #$NON-NLS-4$ #$NON-NLS-5$ #$NON-NLS-6$ #$NON-NLS-7$ #$NON-NLS-8$ imgList.addImage( img, registry.getBitmap( u"images/perspectives/standard/navigator/%s.png" % img)) #$NON-NLS-1$ return imgList # end _createTreeImageList() def _bindWidgetEvents(self): ZBoxedView._bindWidgetEvents(self) self.Bind(wx.EVT_TREE_SEL_CHANGED, self.onSelectionChanged, self.treeView) self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.onItemRightClick, self.treeView) self.Bind(wx.EVT_BUTTON, self.onDashboardButton, self.dashboardButton) self.Bind(wx.EVT_BUTTON, self.onCollapseAllButton, self.collapseAllButton) self.Bind(ZEVT_REFRESH, self.onZoundryRefresh, self) wx.EVT_SET_FOCUS(self.treeView, self.onFocus) wx.EVT_KILL_FOCUS(self.treeView, self.onUnFocus) # end _bindWidgetEvents() def onFocus(self, event): selection = self._getCurrentSelection() if selection: fireViewSelectionEvent(selection, self) event.Skip() # end onFocus() def onUnFocus(self, event): selection = self._getCurrentSelection() if selection: fireViewUnselectionEvent() event.Skip() # end onUnFocus() def onDashboardButton(self, event): self.treeView.UnselectAll() fireViewSelectionEvent( ZViewSelection(IZViewSelectionTypes.UNPUBLISHED_ACCOUNT_SELECTION, None), self) event.Skip() # end onDashboardButton() def onCollapseAllButton(self, event): self.treeView.UnselectAll() self.treeView.collapseAll() fireViewSelectionEvent( ZViewSelection(IZViewSelectionTypes.UNPUBLISHED_ACCOUNT_SELECTION, None), self) event.Skip() # end onCollapseAllButton() def onItemRightClick(self, event): itemId = event.GetItem() node = self.treeView.GetPyData(itemId) nodeType = node.getType() if nodeType == NODE_TYPE_ACCOUNT: account = node.getAccount() menu = self._createAccountCtxMenu(account) self.PopupMenu(menu) menu.Destroy() if nodeType == NODE_TYPE_BLOG: blog = node.getBlog() menu = self._createBlogCtxMenu(blog) self.PopupMenu(menu) menu.Destroy() event.Skip() # end onItemRightClick() def _createAccountCtxMenu(self, account): menuContext = ZAccountMenuActionContext(self, account) menuModel = ZBlogAccountMenuModel() provider = ZModelBasedMenuContentProvider(menuModel, menuContext) eventHandler = ZModelBasedMenuEventHandler(menuModel, menuContext) return ZMenu(self, menuModel.getRootNode(), provider, eventHandler) # end _createAccountCtxMenu() def _createBlogCtxMenu(self, blog): menuContext = ZBlogMenuActionContext(self, blog) menuModel = ZBlogMenuModel() provider = ZModelBasedMenuContentProvider(menuModel, menuContext) eventHandler = ZModelBasedMenuEventHandler(menuModel, menuContext) return ZMenu(self, menuModel.getRootNode(), provider, eventHandler) # end _createBlogCtxMenu() def onSelectionChanged(self, event): selection = self._getCurrentSelection() if selection: fireViewSelectionEvent(selection, self) else: fireViewUnselectionEvent() event.Skip() # end _onSelectionChanged() def onAccountAdded(self, account): self.accountEventQueue.put((ACCOUNT_EVENT_ADD, account)) self.model.addAccount(account) fireRefreshEvent(self) # end onAccountAdded() def onAccountChanged(self, account): self.accountEventQueue.put((ACCOUNT_EVENT_UPDATE, account)) self.model.updateAccount(account) fireRefreshEvent(self) # end onAccountChange() def onAccountDeleted(self, account): self.accountEventQueue.put((ACCOUNT_EVENT_DELETE, account)) self.model.removeAccount(account) fireRefreshEvent(self) # end onAccountDeleted() def onIndexChange(self, event): shouldRefresh = event.getEventType() == IZDocIndexEvent.DOCINDEX_EVENTTYPE_ADD or \ event.getEventType() == IZDocIndexEvent.DOCINDEX_EVENTTYPE_REMOVE if shouldRefresh: self.indexEventQueue.put(event) fireRefreshEvent(self) # end onIndexChange() def onBlogEntryDropped(self, blogId, node): getLoggerService().debug( u"Dropped blog entry '%s' onto blog node '%s'." % (blogId, node.getBlog().getId())) #$NON-NLS-1$ ZShowNotYetImplementedMessage(self) # end onBlogEntryDropped() def onZoundryRefresh(self, event): #@UnusedVariable nodesToRefresh = self._getNodesToRefresh() self.treeView.refresh(nodesToRefresh) # end onZoundryRefresh() # Gets the list of nodes to refresh based on the current queue of index events. def _getNodesToRefresh(self): nodesToRefresh = [] # If there are any account events, refresh the whole tree if not self.accountEventQueue.empty(): # Clear out the account event queue while not self.accountEventQueue.empty(): self.accountEventQueue.get() return None # If there are index events, then we can refresh only parts of the tree while not self.indexEventQueue.empty(): event = self.indexEventQueue.get() dirtyNodes = None if event.getEventType() == IZDocIndexEvent.DOCINDEX_EVENTTYPE_ADD: if event.getDataType( ) == IZDocIndexEvent.DOCINDEX_DATATYPE_DOCUMENT: dirtyNodes = self.model.addDocumentIDO( event.getDocumentIDO()) elif event.getDataType( ) == IZDocIndexEvent.DOCINDEX_DATATYPE_IMAGE: dirtyNodes = self.model.addImageIDO(event.getImageIDO()) elif event.getDataType( ) == IZDocIndexEvent.DOCINDEX_DATATYPE_LINK: dirtyNodes = self.model.addLinkIDO(event.getLinkIDO()) elif event.getDataType( ) == IZDocIndexEvent.DOCINDEX_DATATYPE_TAG: dirtyNodes = self.model.addTagIDO(event.getTagIDO()) elif event.getEventType( ) == IZDocIndexEvent.DOCINDEX_EVENTTYPE_REMOVE: if event.getDataType( ) == IZDocIndexEvent.DOCINDEX_DATATYPE_DOCUMENT: dirtyNodes = self.model.removeDocumentIDO( event.getDocumentIDO()) elif event.getDataType( ) == IZDocIndexEvent.DOCINDEX_DATATYPE_IMAGE: dirtyNodes = self.model.removeImageIDO(event.getImageIDO()) elif event.getDataType( ) == IZDocIndexEvent.DOCINDEX_DATATYPE_LINK: dirtyNodes = self.model.removeLinkIDO(event.getLinkIDO()) elif event.getDataType( ) == IZDocIndexEvent.DOCINDEX_DATATYPE_TAG: dirtyNodes = self.model.removeTagIDO(event.getTagIDO()) if dirtyNodes is not None: nodesToRefresh.extend(dirtyNodes) return nodesToRefresh # end _getNodesToRefresh() def _getCurrentSelection(self): treeIDs = self.treeView.GetSelections() nodes = map(self.treeView.GetPyData, treeIDs) # Just return the 1st node - currently multi-selection is disabled. for node in nodes: return createViewSelection(node) return None # end _getCurrentSelection() def destroy(self): self._saveTreeLayout() self._unregisterAsListener() # end destroy() def _saveTreeLayout(self): visitor = ZTreeLayoutSaveVisitor() self.treeView.accept(visitor) self._saveTreeSelection() # Save the properties getApplicationModel().getUserProfile().getProperties().save() # end _saveTreeLayout() def _saveTreeSelection(self): nodes = self.treeView.getSelectedNodes() hashValue = 0 if nodes: node = nodes[0] hashValue = node.hashCode() userPrefs = getApplicationModel().getUserProfile().getPreferences() userPrefs.setUserPreference( IZBlogAppUserPrefsKeys.NAVIGATOR_VIEW_SELECTION, unicode(hashValue)) # end _saveTreeSelection() def _restoreTreeSelection(self): userPrefs = getApplicationModel().getUserProfile().getPreferences() hashValue = userPrefs.getUserPreferenceInt( IZBlogAppUserPrefsKeys.NAVIGATOR_VIEW_SELECTION, 0) if hashValue != 0: visitor = ZTreeSelectionRestoreVisitor(self, hashValue) self.treeView.accept(visitor) # end _restoreTreeSelection() def _registerAsListener(self): self._registerAsAccountListener() self._registerAsIndexListener() # end _registerAsListener() def _unregisterAsListener(self): self._unregisterAsAccountListener() self._unregisterAsIndexListener() # end _unregisterAsListener() def _registerAsAccountListener(self): engine = getApplicationModel().getEngine() accountStore = engine.getService( IZBlogAppServiceIDs.ACCOUNT_STORE_SERVICE_ID) accountStore.addListener(self) # end _registerAsAccountListener() def _unregisterAsAccountListener(self): engine = getApplicationModel().getEngine() accountStore = engine.getService( IZBlogAppServiceIDs.ACCOUNT_STORE_SERVICE_ID) accountStore.removeListener(self) # end _unregisterAsAccountListener() def _registerAsIndexListener(self): engine = getApplicationModel().getEngine() accountStore = engine.getService( IZBlogAppServiceIDs.DOCUMENT_INDEX_SERVICE_ID) accountStore.addListener(self) # end _registerAsIndexListener() def _unregisterAsIndexListener(self): engine = getApplicationModel().getEngine() accountStore = engine.getService( IZBlogAppServiceIDs.DOCUMENT_INDEX_SERVICE_ID) accountStore.removeListener(self)
class ZLinksView(ZBoxedView, IZDocumentIndexListener): def __init__(self, parent): self.link = None self.blog = None self.indexService = getApplicationModel().getService(IZBlogAppServiceIDs.DOCUMENT_INDEX_SERVICE_ID) self.accountStore = getApplicationModel().getService(IZBlogAppServiceIDs.ACCOUNT_STORE_SERVICE_ID) self.model = ZContextInfoLinksModel(ZLinkSearchFilter()) self.openLinkAction = getApplicationModel().getActionRegistry().findAction(IZAppActionIDs.OPEN_LINK_ACTION) ZBoxedView.__init__(self, parent) self._registerAsIndexListener() self.validSelection = False # end __init__() def getViewId(self): return IZViewIds.LINKS_LIST_VIEW # end getViewId() def _getHeaderBitmap(self): return getResourceRegistry().getBitmap(u"images/perspectives/standard/links.png") #$NON-NLS-1$ # end _getHeaderBitmap() def _getHeaderLabel(self): return _extstr(u"linksview.Links") #$NON-NLS-1$ # end _getHeaderLabel() def _createHeaderWidgets(self, parent, widgetList): choices = self._getSearchBoxChoices() bitmap = getResourceRegistry().getBitmap(u"images/perspectives/standard/contextinfo/linksview/search.png") #$NON-NLS-1$ self.searchTextBox = ZAdvancedTextBox(parent, bitmap, choices, False) self.searchTextBox.setCurrentChoice(SEARCH_HOST) self.searchTextBox.SetSizeHints(220, -1) widgetList.append(self.searchTextBox) # end _createHeaderWidgets() def _createContentWidgets(self, parent): treeStyle = wx.TR_HIDE_ROOT | wx.TR_LINES_AT_ROOT | wx.TR_SINGLE | wx.TR_HAS_BUTTONS | wx.NO_BORDER provider = ZLinkTreeContentProvider(self.model) self.linksTreeView = ZTreeView(provider, parent, style = treeStyle) # end _createContentWidgets() def _layoutContentWidgets(self): box = wx.BoxSizer(wx.VERTICAL) box.Add(self.linksTreeView, 1, wx.EXPAND) return box # end _layoutContentWidgets() def _bindWidgetEvents(self): ZBoxedView._bindWidgetEvents(self) self.Bind(ZEVT_REFRESH, self.onZoundryRefresh, self) self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.onLinkActivated, self.linksTreeView) self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.onLinkRightClick, self.linksTreeView) self.Bind(wx.EVT_TREE_SEL_CHANGED, self.onLinkSelected, self.linksTreeView) # self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.onEntryBeginDrag, self.linksTreeView) self.Bind(wx.EVT_TEXT_ENTER, self.onSearchText, self.searchTextBox) self.Bind(ZEVT_VIEW_SELECTION_CHANGED, self.onViewSelectionChanged) wx.EVT_SET_FOCUS(self.linksTreeView, self.onFocus) wx.EVT_KILL_FOCUS(self.linksTreeView, self.onUnFocus) # end _bindWidgetEvents() def refreshContent(self, selection): (accountId, blogId) = selection.getData() filter = ZLinkSearchFilter() if blogId is not None: account = self.accountStore.getAccountById(accountId) self.blog = account.getBlogById(blogId) filter.setAccountIdCriteria(accountId) filter.setBlogIdCriteria(blogId) else: self.blog = None filter.setAccountIdCriteria(IZLinkSearchFilter.UNPUBLISHED_ACCOUNT_ID) filter.setBlogIdCriteria(IZLinkSearchFilter.UNPUBLISHED_BLOG_ID) self.model = ZContextInfoLinksModel(filter) self.linksTreeView.setContentProvider(ZLinkTreeContentProvider(self.model)) self.linksTreeView.refresh() self.linksTreeView.deselectAll() self.onInvalidSelection() fireViewUnselectionEvent() # end refreshContent() def onViewSelectionChanged(self, event): if event.getSelection().getType() == IZViewSelectionTypes.BLOG_LINKS_SELECTION: self.refreshContent(event.getSelection()) # end onViewSelectionChanged() def onFocus(self, event): if self.link: fireViewSelectionEvent(ZLinkSelection(self.link, self.blog), self) else: fireViewUnselectionEvent() event.Skip() # end onFocus() def onUnFocus(self, event): fireViewUnselectionEvent() event.Skip() # end onUnFocus() def onSearchText(self, event): self.model.setHostCriteria(event.GetString()) self.model.refresh() self.linksTreeView.clear() self.linksTreeView.refresh() self.linksTreeView.deselectAll() self.onInvalidSelection() fireViewEvent(ZViewEvent(VIEWLINKSFILTERCHANGEDEVENT, self)) event.Skip() # end onSearchText() # # def onEntryBeginDrag(self, event): # index = event.GetIndex() # docIDO = self.model.getEntry(index) # docId = docIDO.getId() # # # FIXME also add some sort of custom format for dragging to the Explorer/TextPad (use a composite data object) # data = ZBlogPostDataObjectInternal(docId) # dragSource = wx.DropSource(self) # dragSource.SetData(data) # dragSource.DoDragDrop(wx.Drag_CopyOnly) # event.Skip() # # end onEntryBeginDrag() def _updateModel(self, refreshData): (eventType, linkIDO) = refreshData shouldRefresh = False if eventType == IZDocIndexEvent.DOCINDEX_EVENTTYPE_ADD: shouldRefresh = self.model.addLink(linkIDO) elif eventType == IZDocIndexEvent.DOCINDEX_EVENTTYPE_REMOVE: shouldRefresh = self.model.removeLink(linkIDO) elif eventType == IZDocIndexEvent.DOCINDEX_EVENTTYPE_UPDATE: shouldRefresh = self.model.updateLink(linkIDO) return shouldRefresh # end _updateModel() # This is the only method that can happen on a non-UI thread. It will # gather up the needed data, then fire a "refresh ui" event. That event # will get picked up by the UI thread and the view will refresh. def onIndexChange(self, event): if event.getDataType() == IZDocIndexEvent.DOCINDEX_DATATYPE_LINK: refreshData = (event.getEventType(), event.getLinkIDO()) fireRefreshEvent(self, refreshData) # end onIndexChange() def onZoundryRefresh(self, event): if self._updateModel(event.getData()): self.linksTreeView.refresh() event.Skip() # end onZoundryRefresh() def onLinkActivated(self, event): node = self.linksTreeView.GetPyData(event.GetItem()) if isinstance(node, ZLinkIDONode): link = node.getLinkIDO() context = ZLinkIDOActionContext(self, link) self.openLinkAction.runAction(context) event.Skip # end onLinkActivated() def onLinkRightClick(self, event): node = self.linksTreeView.GetPyData(event.GetItem()) if isinstance(node, ZLinkIDONode): link = node.getLinkIDO() context = ZLinkIDOActionContext(self, link) menuModel = ZLinkMenuModel() menu = ZModelBasedMenu(menuModel, context, self) self.PopupMenu(menu) menu.Destroy() event.Skip() # end onLinkRightClick() def onLinkSelected(self, event): node = self.linksTreeView.GetPyData(event.GetItem()) if isinstance(node, ZLinkIDONode): self.link = node.getLinkIDO() if self.link: fireViewSelectionEvent(ZLinkSelection(self.link, self.blog), self) else: fireViewUnselectionEvent() event.Skip() # end onLinkSelected() def onInvalidSelection(self): self.link = None # end onInvalidSelection() def destroy(self): self._unregisterAsIndexListener() # end destroy() def _registerAsIndexListener(self): self.indexService.addListener(self) # end _registerAsIndexListener() def _unregisterAsIndexListener(self): self.indexService.removeListener(self) # end _unregisterAsIndexListener() def _getSearchBoxChoices(self): return [ (u"Host", None, SEARCH_HOST), #$NON-NLS-1$ ]
class ZPreferencesDialog(ZHeaderDialog): def __init__(self, parent, jumpToPageId=None): self.currentSelection = None self.currentPage = None self.currentPageId = None self.pageCache = {} style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER title = self._getDialogTitle() size = self._getInitialSize() ZHeaderDialog.__init__(self, parent, wx.ID_ANY, title, name=u"PrefsDialog", style=style, size=size) #$NON-NLS-1$ self._enableButtons(False) self.jumpToPage(jumpToPageId) self.prefsTreeView.SetFocus() # end __init__() def _getNonHeaderContentBorder(self): return 0 # end _getNonHeaderContentBorder() def _createNonHeaderWidgets(self): self.splitterWindow = ZSplitterWindow(self) self.splitterWindow.SetMinimumPaneSize(100) self.splitterWindow.SetSashSize(3) self.leftPanel = self._createLeftTreePanel() self.currentPage = self._createDefaultPage() self.currentPageId = None self.splitterWindow.SplitVertically(self.leftPanel, self.currentPage, 175) self.lowerStaticLine = wx.StaticLine(self) # end _createNonHeaderWidgets() def _createLeftTreePanel(self): panel = ZTransparentPanel(self.splitterWindow, wx.ID_ANY, style=wx.NO_BORDER) # Create the prefs tree view. provider = self._createTreeProvider() treeStyle = wx.NO_BORDER | wx.TR_HIDE_ROOT | wx.TR_LINES_AT_ROOT | wx.TR_SINGLE | wx.TR_HAS_BUTTONS self.prefsTreeView = ZTreeView(provider, panel, style=treeStyle) self.prefsTreeView.refresh() self.treeButtons = self._createTreeButtons(panel) # Create a little static vertical line (aesthetic only) self.middleStaticLine = wx.StaticLine(panel, style=wx.LI_VERTICAL) return panel # end _createLeftTreePanel() def _createTreeButtons(self, parent): #@UnusedVariable return [] # end _createTreeButtons() # This is the page created when no pref page is selected. def _createDefaultPage(self): defaultPrefPage = ZDefaultPreferencePage(self.splitterWindow) return defaultPrefPage # end _createDefaultPage() def _populateNonHeaderWidgets(self): self._enableApplyButton(False) # end _populateNonHeaderWidgets() def _layoutNonHeaderWidgets(self): treeSizer = wx.BoxSizer(wx.VERTICAL) treeSizer.Add(self.prefsTreeView, 1, wx.EXPAND) for button in self.treeButtons: treeSizer.Add(button, 0, wx.EXPAND | wx.ALL, 2) leftPanelSizer = wx.BoxSizer(wx.HORIZONTAL) leftPanelSizer.Add(treeSizer, 1, wx.EXPAND) leftPanelSizer.Add(self.middleStaticLine, 0, wx.EXPAND) self.leftPanel.SetAutoLayout(True) self.leftPanel.SetSizer(leftPanelSizer) self.leftPanel.Layout() verticalSizer = wx.BoxSizer(wx.VERTICAL) verticalSizer.Add(self.splitterWindow, 1, wx.EXPAND) verticalSizer.Add(self.lowerStaticLine, 0, wx.EXPAND) return verticalSizer # end _layoutNonHeaderWidgets() def _bindWidgetEvents(self): self.Bind(wx.EVT_TREE_SEL_CHANGED, self.onTreeItemSelected, self.prefsTreeView) self.Bind(wx.EVT_TREE_SEL_CHANGING, self.onTreeItemChanging, self.prefsTreeView) self._bindOkButton(self.onOK) self._bindCancelButton(self.onCancel) self._bindApplyButton(self.onApply) # end _bindWidgetEvents() def onTreeItemChanging(self, event): if self.currentPage is not None: if self.currentPage.isDirty(): # FIXME (EPW) provide override for this message and title if not ZShowYesNoMessage( self, _extstr(u"prefsdialog.PrefPageSwitchMessage"), _extstr(u"prefsdialog.DiscardChanges") ): #$NON-NLS-2$ #$NON-NLS-1$ event.Veto() return else: self.currentPage.rollback() event.Skip() # end onTreeItemChanging() def onTreeItemSelected(self, event): node = self.prefsTreeView.GetPyData(event.GetItem()) self.currentSelection = node self._updateHeader() self._changePreferencePage() event.Skip() # end onTreeItemSelected() # This method is called when the user is changing to a new preference page. def _changePreferencePage(self): oldPage = self.currentPage oldPage.Show(False) if self.currentSelection is None: self.currentPage = self._createDefaultPage() self.currentPage.Show(True) elif self.currentSelection in self.pageCache: self.currentPage = self.pageCache[self.currentSelection] self.currentPage.Show(True) else: # Construct the preference page. self.currentPage = self._createPrefPage(self.splitterWindow, self.currentSelection) self.currentPage.setPrefsDialog(self) # Create, populate, layout the page. self.currentPage.createWidgets() self.currentPage.bindWidgetEvents() self.currentPage.populateWidgets() self.currentPage.layoutWidgets() self.pageCache[self.currentSelection] = self.currentPage # Call rollback here, which should clear out the page's session # and force it to update its visual state (this is useful when one # pref page's initial visual state depends on another page's data, # which may have changed since this page was created). self.currentPage.rollback() self.currentPageId = self._resolveNodeId(self.currentSelection) self.splitterWindow.ReplaceWindow(oldPage, self.currentPage) self.splitterWindow.Layout() self.currentPage.Layout() # end _changePreferencePage() def _getButtonTypes(self): return ZBaseDialog.OK_BUTTON | ZBaseDialog.CANCEL_BUTTON | ZBaseDialog.APPLY_BUTTON # end _getButtonTypes() # Called by the active pref page when the user changes something. def onPrefPageChange(self): if self.currentPage is not None: if self.currentPage.isDirty() and self.currentPage.isValid(): self._enableButtons(True) else: self._enableButtons(False) # end onPrefPageChange() def _enableButtons(self, enabled=True): self._enableOkButton(enabled) self._enableApplyButton(enabled) cancelButton = self.FindWindowById(wx.ID_CANCEL) if enabled: cancelButton.SetLabel(_extstr(u"Cancel")) #$NON-NLS-1$ else: cancelButton.SetLabel(_extstr(u"Close")) #$NON-NLS-1$ # end _enableButtons() def onOK(self, event): try: self.currentPage.apply() self._destroyPages() except Exception, e: ZShowExceptionMessage(self, e) event.Skip()
class ZPreferencesDialog(ZHeaderDialog): def __init__(self, parent, jumpToPageId = None): self.currentSelection = None self.currentPage = None self.currentPageId = None self.pageCache = {} style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER title = self._getDialogTitle() size = self._getInitialSize() ZHeaderDialog.__init__(self, parent, wx.ID_ANY, title, name = u"PrefsDialog", style = style, size = size) #$NON-NLS-1$ self._enableButtons(False) self.jumpToPage(jumpToPageId) self.prefsTreeView.SetFocus() # end __init__() def _getNonHeaderContentBorder(self): return 0 # end _getNonHeaderContentBorder() def _createNonHeaderWidgets(self): self.splitterWindow = ZSplitterWindow(self) self.splitterWindow.SetMinimumPaneSize(100) self.splitterWindow.SetSashSize(3) self.leftPanel = self._createLeftTreePanel() self.currentPage = self._createDefaultPage() self.currentPageId = None self.splitterWindow.SplitVertically(self.leftPanel, self.currentPage, 175) self.lowerStaticLine = wx.StaticLine(self) # end _createNonHeaderWidgets() def _createLeftTreePanel(self): panel = ZTransparentPanel(self.splitterWindow, wx.ID_ANY, style = wx.NO_BORDER) # Create the prefs tree view. provider = self._createTreeProvider() treeStyle = wx.NO_BORDER | wx.TR_HIDE_ROOT | wx.TR_LINES_AT_ROOT | wx.TR_SINGLE | wx.TR_HAS_BUTTONS self.prefsTreeView = ZTreeView(provider, panel, style = treeStyle) self.prefsTreeView.refresh() self.treeButtons = self._createTreeButtons(panel) # Create a little static vertical line (aesthetic only) self.middleStaticLine = wx.StaticLine(panel, style = wx.LI_VERTICAL) return panel # end _createLeftTreePanel() def _createTreeButtons(self, parent): #@UnusedVariable return [] # end _createTreeButtons() # This is the page created when no pref page is selected. def _createDefaultPage(self): defaultPrefPage = ZDefaultPreferencePage(self.splitterWindow) return defaultPrefPage # end _createDefaultPage() def _populateNonHeaderWidgets(self): self._enableApplyButton(False) # end _populateNonHeaderWidgets() def _layoutNonHeaderWidgets(self): treeSizer = wx.BoxSizer(wx.VERTICAL) treeSizer.Add(self.prefsTreeView, 1, wx.EXPAND) for button in self.treeButtons: treeSizer.Add(button, 0, wx.EXPAND | wx.ALL, 2) leftPanelSizer = wx.BoxSizer(wx.HORIZONTAL) leftPanelSizer.Add(treeSizer, 1, wx.EXPAND) leftPanelSizer.Add(self.middleStaticLine, 0, wx.EXPAND) self.leftPanel.SetAutoLayout(True) self.leftPanel.SetSizer(leftPanelSizer) self.leftPanel.Layout() verticalSizer = wx.BoxSizer(wx.VERTICAL) verticalSizer.Add(self.splitterWindow, 1, wx.EXPAND) verticalSizer.Add(self.lowerStaticLine, 0, wx.EXPAND) return verticalSizer # end _layoutNonHeaderWidgets() def _bindWidgetEvents(self): self.Bind(wx.EVT_TREE_SEL_CHANGED, self.onTreeItemSelected, self.prefsTreeView) self.Bind(wx.EVT_TREE_SEL_CHANGING, self.onTreeItemChanging, self.prefsTreeView) self._bindOkButton(self.onOK) self._bindCancelButton(self.onCancel) self._bindApplyButton(self.onApply) # end _bindWidgetEvents() def onTreeItemChanging(self, event): if self.currentPage is not None: if self.currentPage.isDirty(): # FIXME (EPW) provide override for this message and title if not ZShowYesNoMessage(self, _extstr(u"prefsdialog.PrefPageSwitchMessage"), _extstr(u"prefsdialog.DiscardChanges")): #$NON-NLS-2$ #$NON-NLS-1$ event.Veto() return else: self.currentPage.rollback() event.Skip() # end onTreeItemChanging() def onTreeItemSelected(self, event): node = self.prefsTreeView.GetPyData(event.GetItem()) self.currentSelection = node self._updateHeader() self._changePreferencePage() event.Skip() # end onTreeItemSelected() # This method is called when the user is changing to a new preference page. def _changePreferencePage(self): oldPage = self.currentPage oldPage.Show(False) if self.currentSelection is None: self.currentPage = self._createDefaultPage() self.currentPage.Show(True) elif self.currentSelection in self.pageCache: self.currentPage = self.pageCache[self.currentSelection] self.currentPage.Show(True) else: # Construct the preference page. self.currentPage = self._createPrefPage(self.splitterWindow, self.currentSelection) self.currentPage.setPrefsDialog(self) # Create, populate, layout the page. self.currentPage.createWidgets() self.currentPage.bindWidgetEvents() self.currentPage.populateWidgets() self.currentPage.layoutWidgets() self.pageCache[self.currentSelection] = self.currentPage # Call rollback here, which should clear out the page's session # and force it to update its visual state (this is useful when one # pref page's initial visual state depends on another page's data, # which may have changed since this page was created). self.currentPage.rollback() self.currentPageId = self._resolveNodeId(self.currentSelection) self.splitterWindow.ReplaceWindow(oldPage, self.currentPage) self.splitterWindow.Layout() self.currentPage.Layout() # end _changePreferencePage() def _getButtonTypes(self): return ZBaseDialog.OK_BUTTON | ZBaseDialog.CANCEL_BUTTON | ZBaseDialog.APPLY_BUTTON # end _getButtonTypes() # Called by the active pref page when the user changes something. def onPrefPageChange(self): if self.currentPage is not None: if self.currentPage.isDirty() and self.currentPage.isValid(): self._enableButtons(True) else: self._enableButtons(False) # end onPrefPageChange() def _enableButtons(self, enabled = True): self._enableOkButton(enabled) self._enableApplyButton(enabled) cancelButton = self.FindWindowById(wx.ID_CANCEL) if enabled: cancelButton.SetLabel(_extstr(u"Cancel")) #$NON-NLS-1$ else: cancelButton.SetLabel(_extstr(u"Close")) #$NON-NLS-1$ # end _enableButtons() def onOK(self, event): try: self.currentPage.apply() self._destroyPages() except Exception, e: ZShowExceptionMessage(self, e) event.Skip()