class ContainerManager(ContainerManagerMeta): onViewAddedToContainer = Event() __DESTROY_ORDER = (ViewTypes.DEFAULT, ViewTypes.LOBBY_SUB, ViewTypes.WINDOW, ViewTypes.BROWSER, ViewTypes.TOP_WINDOW, ViewTypes.WAITING, ViewTypes.CURSOR, ViewTypes.SERVICE_LAYOUT) __CONTAINERS_TO_CLEAR = (ViewTypes.WINDOW, ViewTypes.BROWSER, ViewTypes.TOP_WINDOW) def __init__(self, loader): super(ContainerManager, self).__init__() proxy = weakref.proxy(self) self.__containers = {ViewTypes.DEFAULT: _DefaultContainer(proxy), ViewTypes.CURSOR: _DefaultContainer(proxy), ViewTypes.WAITING: _DefaultContainer(proxy), ViewTypes.WINDOW: _PopUpContainer(proxy), ViewTypes.BROWSER: _PopUpContainer(proxy), ViewTypes.TOP_WINDOW: _PopUpContainer(proxy), ViewTypes.SERVICE_LAYOUT: _DefaultContainer(proxy)} self._loadingViews = dict() self.__loader = loader self.__loader.onViewLoaded += self.__loader_onViewLoaded self.__scopeController = GlobalScopeController() self.__scopeController.create() def load(self, alias, name = None, *args, **kwargs): if name is None: name = alias isViewExists = self.as_getViewS(name) if not isViewExists and (alias, name) not in self._loadingViews: pyEntity = self.__loader.loadView(alias, name, *args, **kwargs) self.__scopeController.addLoadingView(pyEntity, False) curType = pyEntity.settings.type if self.canCancelPreviousLoading(curType): result = [] for kev, val in self._loadingViews.iteritems(): if val.settings.type == pyEntity.settings.type: result.append(val) if len(result) > 0: self.__cancelLoadingForPyEntities(result) self._loadingViews[alias, name] = pyEntity return def __cancelLoadingForPyEntities(self, pyEntities): for curEntity in pyEntities: self._loadingViews.pop((curEntity.settings.alias, curEntity.uniqueName)) self.__loader.cancelLoadingByName(curEntity.uniqueName) curEntity.destroy() def canCancelPreviousLoading(self, containerType): container = self.getContainer(containerType) if container is not None: return container.canCancelPreviousLoading() else: return False return def addContainer(self, containerType, name, container = None): result = True if containerType not in self.__containers: if container is None: self.__containers[containerType] = _DefaultContainer(weakref.proxy(self)) self.as_registerContainerS(containerType, name) elif isinstance(container, IViewContainer): self.__containers[containerType] = container self.as_registerContainerS(containerType, name) else: LOG_ERROR('Container must be implemented IViewContainer', container) result = False else: LOG_ERROR('Container already registered', containerType) result = False return result def removeContainer(self, viewType): self.__scopeController.removeSubScopeController(ScopeTemplates.VIEW_TYPES_TO_SCOPES[viewType].getScopeType()) result = True if viewType in self.__containers: container = self.__containers[viewType] container.destroy() self.as_unregisterContainerS(viewType) del self.__containers[viewType] else: result = False return result def getContainer(self, viewType): if viewType in self.__containers: return self.__containers[viewType] else: return None def isModalViewsIsExists(self): if self.getContainer(ViewTypes.TOP_WINDOW).getViewCount(isModal=True) > 0: return True elif self.getContainer(ViewTypes.BROWSER).getViewCount(isModal=True) > 0: return True else: return self.getContainer(ViewTypes.WINDOW).getViewCount(isModal=True) > 0 def getView(self, viewType, criteria = None): view = None container = self.getContainer(viewType) if container is not None: view = container.getView(criteria=criteria) else: raise Exception('Container for %s view is None!' % viewType) return view def isViewAvailable(self, viewType, criteria = None): container = self.getContainer(viewType) if container is not None: return container.getView(criteria=criteria) is not None else: return False return def closePopUps(self): self.as_closePopUpsS() def clear(self): for c in self.__CONTAINERS_TO_CLEAR: self.getContainer(c).clear() def _dispose(self): if self.__loader is not None: self.__loader.onViewLoaded -= self.__loader_onViewLoaded self.__loader = None for viewType in self.__DESTROY_ORDER: if viewType in self.__containers: container = self.__containers.pop(viewType) LOG_DEBUG('CONTAINER: ' + str(container) + '/' + viewType) container.destroy() if len(self.__containers): LOG_ERROR('No all containers are destructed.') self.__containers.clear() self.onViewAddedToContainer.clear() self.__scopeController.destroy() self.__scopeController = None self._loadingViews.clear() self._loadingViews = None super(ContainerManager, self)._dispose() return def __loader_onViewLoaded(self, pyView): viewType = pyView.settings.type if viewType is None: LOG_ERROR('Type of view is not defined', pyView.settings) viewKey = (pyView.alias, pyView.uniqueName) if viewKey in self._loadingViews: self._loadingViews.pop(viewKey) if viewType in self.__containers: if ViewTypes.DEFAULT == viewType: self.closePopUps() if self.__scopeController.isViewLoading(pyView): container = self.__containers[viewType] if container.add(pyView): self.__scopeController.addView(pyView, False) self.as_showS(pyView.uniqueName, 0, 0) pyView.create() subContainerType = pyView.getSubContainerType() if subContainerType is not None: self.addContainer(subContainerType, pyView.uniqueName) LOG_DEBUG('View added to container', pyView) self.onViewAddedToContainer(container, pyView) else: LOG_DEBUG('"%s" view cancelled to load, because its scope has been destroyed.' % str(pyView)) self.as_hideS(pyView.uniqueName) pyView.destroy() else: LOG_ERROR('Type "%s" of view "%s" is not supported' % (viewType, pyView)) return
class ContainerManager(ContainerManagerMeta): """ Class of container manager. """ def __init__(self, loader, *containers): super(ContainerManager, self).__init__() self.onViewAddedToContainer = Event() proxy = weakref.proxy(self) self.__containers = {} for container in containers: raise isinstance(container, AbstractViewContainer) or AssertionError self.__containers[container.getViewType()] = container(proxy) self._loadingViews = dict() self.__loader = loader self.__loader.onViewLoaded += self.__loader_onViewLoaded self.__scopeController = GlobalScopeController() self.__scopeController.create() def load(self, alias, name = None, *args, **kwargs): """ Loads view to container. :param alias: :param name: :param args: :param kwargs: :return: """ if name is None: name = alias isViewExists = self.as_getViewS(name) if not isViewExists and (alias, name) not in self._loadingViews: pyEntity = self.__loader.loadView(alias, name, *args, **kwargs) self.__scopeController.addLoadingView(pyEntity, False) curType = pyEntity.settings.type if self.canCancelPreviousLoading(curType): result = [] for kev, val in self._loadingViews.iteritems(): if val.settings.type == pyEntity.settings.type: result.append(val) if result: self.__cancelLoadingForPyEntities(result) self._loadingViews[alias, name] = pyEntity return def canCancelPreviousLoading(self, containerType): container = self.getContainer(containerType) if container is not None: return container.canCancelPreviousLoading() else: return False return def addContainer(self, viewType, name, container = None): result = True if viewType not in self.__containers: if container is None: self.__containers[viewType] = DefaultContainer(viewType, weakref.proxy(self)) self.as_registerContainerS(viewType, name) elif isinstance(container, AbstractViewContainer): self.__containers[viewType] = container self.as_registerContainerS(viewType, name) else: LOG_ERROR('Container must be implemented IViewContainer', container) result = False else: LOG_ERROR('Container already registered', viewType) result = False return result def removeContainer(self, viewType): self.__scopeController.removeSubScopeController(ScopeTemplates.VIEW_TYPES_TO_SCOPES[viewType].getScopeType()) result = True if viewType in self.__containers: container = self.__containers[viewType] container.destroy() self.as_unregisterContainerS(viewType) del self.__containers[viewType] else: result = False return result def getContainer(self, viewType): if viewType in self.__containers: return self.__containers[viewType] else: return None def isModalViewsIsExists(self): for viewType in _POPUPS_CONTAINERS: container = self.getContainer(viewType) if container is not None and container.getViewCount(isModal=True): return True return False def getView(self, viewType, criteria = None): container = self.getContainer(viewType) if container is not None: view = container.getView(criteria=criteria) else: raise Exception('Container for %s view is None!' % viewType) return view def isViewAvailable(self, viewType, criteria = None): container = self.getContainer(viewType) if container is not None: return container.getView(criteria=criteria) is not None else: return False return def showContainers(self, *viewTypes): self.as_showContainersS(viewTypes) def hideContainers(self, *viewTypes): self.as_hideContainersS(viewTypes) def isContainerShown(self, viewType): return self.as_isContainerShownS(viewType) def closePopUps(self): self.as_closePopUpsS() def clear(self): for viewType in _POPUPS_CONTAINERS: container = self.getContainer(viewType) if container is not None: container.clear() return def removeLoadingView(self, alias, uniqueName): self._loadingViews.pop((alias, uniqueName), None) return def _dispose(self): if self.__loader is not None: self.__loader.onViewLoaded -= self.__loader_onViewLoaded self.__loader = None for viewType in _CONTAINERS_DESTROY_ORDER: if viewType in self.__containers: container = self.__containers.pop(viewType) LOG_DEBUG('CONTAINER: {}/{}'.format(container, viewType)) container.destroy() if len(self.__containers): LOG_ERROR('No all containers are destructed.') self.__containers.clear() self.onViewAddedToContainer.clear() self.__scopeController.destroy() self.__scopeController = None self._loadingViews.clear() self._loadingViews = None super(ContainerManager, self)._dispose() return def __cancelLoadingForPyEntities(self, pyEntities): for curEntity in pyEntities: self._loadingViews.pop((curEntity.settings.alias, curEntity.uniqueName)) self.__loader.cancelLoadingByName(curEntity.uniqueName) curEntity.destroy() def __loader_onViewLoaded(self, pyView): viewType = pyView.settings.type if viewType is None: LOG_ERROR('Type of view is not defined', pyView.settings) viewKey = (pyView.alias, pyView.uniqueName) if viewKey in self._loadingViews: self._loadingViews.pop(viewKey) if viewType in self.__containers: if ViewTypes.DEFAULT == viewType: self.closePopUps() if self.__scopeController.isViewLoading(pyView): container = self.__containers[viewType] if container.add(pyView): self.__scopeController.addView(pyView, False) self.as_showS(pyView.uniqueName, 0, 0) pyView.create() subContainerType = pyView.getSubContainerType() if subContainerType is not None: self.addContainer(subContainerType, pyView.uniqueName) LOG_DEBUG('View added to container', pyView) self.onViewAddedToContainer(container, pyView) else: LOG_DEBUG('"%s" view cancelled to load, because its scope has been destroyed.' % str(pyView)) self.as_hideS(pyView.uniqueName) pyView.destroy() else: LOG_ERROR('Type "%s" of view "%s" is not supported' % (viewType, pyView)) return
class ContainerManager(ContainerManagerMeta, IContainerManager): def __init__(self, loader, *containers): super(ContainerManager, self).__init__() self.onViewAddedToContainer = Event() self.onViewLoading = Event() self.onViewLoaded = Event() self.__globalContainer = _GlobalViewContainer(weakref.proxy(self)) for container in containers: self.__globalContainer.addChildContainer(container) self.__loader = loader self.__loader.onViewLoadInit += self.__onViewLoadInit self.__loader.onViewLoaded += self.__onViewLoaded self.__scopeController = GlobalScopeController() self.__scopeController.create() self.__viewCache = _ViewCollection() self.__chainMng = _ChainManager(weakref.proxy(self)) def _dispose(self): self.__viewCache.destroy() self.__chainMng.destroy() if self.__loader is not None: self.__loader.onViewLoaded -= self.__onViewLoaded self.__loader.onViewLoadInit -= self.__onViewLoadInit self.__loader = None for viewType in _CONTAINERS_DESTROY_ORDER: container = self.__globalContainer.findContainer(viewType) if container is not None: _logger.debug('Destroy container %s (%r)', viewType, container) container.destroy() self.__globalContainer.destroy() self.onViewAddedToContainer.clear() self.__scopeController.destroy() self.__scopeController = None super(ContainerManager, self)._dispose() return def destroyViews(self, alias, name=None): def compareByAlias(view): return view.key.alias == alias def compareByAliasAndName(view): viewKey = view.key return viewKey.alias == alias and viewKey.name == name if name is None: comparator = compareByAlias else: comparator = compareByAliasAndName views = self.__scopeController.findViews(comparator) views.extend(self.__viewCache.findViews(comparator)) for view in views: if not view.isDisposed(): _logger.debug('The view %r will be destroyed...', view) view.destroy() viewKey = ViewKey(alias, name) chain = self.__chainMng.getChainByViewKey(viewKey) if chain is not None: chain.removeViewByViewKey(viewKey) return def loadChain(self, chainItems): chain = _LoadingChain(chainItems) if self.__chainMng.addChain(chain): chain.run() else: _logger.warning( 'Could not add a new chain. Loading of chain [%r] is canceled.', chainItems) chain.destroy() def load(self, loadParams, *args, **kwargs): viewKey = loadParams.viewKey viewLoadingItem = self.__loader.getViewLoadingItem(viewKey) if viewLoadingItem is not None: _logger.debug('View with key %s is already loading. item=[%r]', viewKey, viewLoadingItem) view = viewLoadingItem.pyEntity if loadParams.loadMode == ViewLoadMode.DEFAULT: loadingViewLoadMode = viewLoadingItem.loadParams.loadMode if loadingViewLoadMode == ViewLoadMode.PRELOAD: viewLoadingItem.loadParams = loadParams self.__addLoadingView(view) elif loadParams.loadMode == ViewLoadMode.PRELOAD: pass else: _logger.warning( 'Unsupported load mode %r. View loading will be skipped.', loadParams) view = None else: view = self.__globalContainer.findView(viewKey) if view is None: view = self.__viewCache.getView(viewKey) if view is None: chain = self.__chainMng.getChainByViewKey(viewKey) if chain is not None: _logger.warning( 'View with loadParams=%r is in the loading chain %r. The request will be skipped.', loadParams, chain) else: _logger.debug( 'Load view with loadParams=%r. Loader=[%r]', loadParams, self.__loader) if loadParams.loadMode == ViewLoadMode.DEFAULT: view = self.__loader.loadView( loadParams, *args, **kwargs) self.__addLoadingView(view) elif loadParams.loadMode == ViewLoadMode.PRELOAD: view = self.__loader.loadView( loadParams, *args, **kwargs) else: _logger.warning( 'Unsupported load mode %r. View loading will be skipped.', loadParams) elif loadParams.loadMode == ViewLoadMode.PRELOAD: _logger.debug( 'View with key %s (%r) is already pre-loaded.', viewKey, view) elif loadParams.loadMode == ViewLoadMode.DEFAULT: _logger.debug( 'Load view with loadParams=%r from the cache. Cache=[%r]', loadParams, self.__viewCache) self.__viewCache.removeView(viewKey) self.__showAndInitializeView(view) view.validate(*args, **kwargs) else: _logger.warning( 'Unsupported load mode %r. View loading will be skipped.', loadParams) view = None else: _logger.debug('View with key %s (%r) is already loaded.', viewKey, view) viewType = view.viewType viewContainer = self.__globalContainer.findContainer(viewType) viewContainer.addView(view) view.validate(*args, **kwargs) return view def getContainer(self, viewType): return self.__globalContainer.findContainer(viewType) def getViewByKey(self, viewKey): if self.__loader is not None: loadingItem = self.__loader.getViewLoadingItem(viewKey) if loadingItem is not None: return loadingItem.pyEntity sources = (self.__globalContainer.findView, self.__viewCache.getView) for source in sources: view = source(viewKey) if view is not None: return view return def isViewCreated(self, viewKey): return self.__globalContainer.findView(viewKey) is not None def isViewInCache(self, viewKey): return self.__viewCache.getView(viewKey) is not None def isModalViewsIsExists(self): for viewType in _POPUPS_CONTAINERS: container = self.__globalContainer.findContainer(viewType) if container is not None and container.getViewCount(isModal=True): return True return False def getView(self, viewType, criteria=None): container = self.__globalContainer.findContainer(viewType) if container is not None: return container.getView(criteria=criteria) else: _logger.warning('Could not found container %s.', viewType) return def isViewAvailable(self, viewType, criteria=None): container = self.__globalContainer.findContainer(viewType) return container.getView( criteria=criteria) is not None if container is not None else False def showContainers(self, *viewTypes): self.as_showContainersS(viewTypes) def hideContainers(self, *viewTypes): self.as_hideContainersS(viewTypes) def isContainerShown(self, viewType): return self.as_isContainerShownS(viewType) def clear(self): for viewType in _POPUPS_CONTAINERS: container = self.__globalContainer.findContainer(viewType) if container is not None: container.clear() return def closePopUps(self): self.as_closePopUpsS() def registerViewContainer(self, viewType, uniqueName): self.as_registerContainerS(viewType, uniqueName) _logger.debug( 'A new container [type=%s, name=%s] has been registered.', viewType, uniqueName) def unregisterViewContainer(self, viewType): self.as_unregisterContainerS(viewType) _logger.debug('The container [type=%s] has been unregistered.', viewType) def __addLoadingView(self, pyView): viewType = pyView.viewType viewContainer = self.__globalContainer.findContainer(viewType) if viewContainer is not None: viewContainer.addLoadingView(pyView) else: _logger.warning( 'Loading of view %r is requested but the container %s is still not exist!', pyView, viewType) self.__scopeController.addLoadingView(pyView, False) return def __showAndInitializeView(self, pyView): viewType = pyView.viewType if viewType is None: _logger.error( 'Type of view is not defined. View %r will be destroyed.', pyView) pyView.destroy() return False else: status = False container = self.__globalContainer.findContainer(viewType) if container is not None: if ViewTypes.DEFAULT == viewType: self.closePopUps() if container.addView(pyView): self.__scopeController.addView(pyView, False) if pyView.uiImpl == UIFrameworkImpl.SCALEFORM: self.as_showS(pyView.uniqueName, 0, 0) pyView.create() self.onViewAddedToContainer(container, pyView) status = True else: _logger.error( '%r view cannot be added to container %r and will be destroyed.', pyView, container) pyView.destroy() else: _logger.error( 'Type %s of view %r is not supported or container has not been properly created', viewType, pyView) pyView.destroy() return status def __addViewToCache(self, pyView): view = self.__viewCache.getView(pyView.key) if view is not None: _logger.warning('The view with key %r is already in the cache.', pyView.key) if view != pyView: view.destroy() if self.__viewCache.addView(pyView): _logger.debug('View %r has been added to the cache %r', pyView, self.__viewCache) else: _logger.debug('Cannot add view %r in the cache %r', pyView, self.__viewCache) elif self.__viewCache.addView(pyView): _logger.debug('View %r has been added to the cache %r', pyView, self.__viewCache) else: _logger.debug('Cannot add view %r in the cache %r', pyView, self.__viewCache) return def __onViewLoaded(self, pyView, loadParams): self.onViewLoaded(pyView) loadMode = loadParams.loadMode if loadMode == ViewLoadMode.DEFAULT: if self.__scopeController.isViewLoading(pyView=pyView): self.__showAndInitializeView(pyView) else: _logger.debug( '%r view loading is cancelled because its scope has been destroyed.', pyView) pyView.destroy() elif loadMode == ViewLoadMode.PRELOAD: self.__addViewToCache(pyView) else: _logger.warning( 'Unsupported load mode %s. View %r will be destroyed.', loadMode, pyView) pyView.destroy() def __onViewLoadInit(self, view, *args, **kwargs): self.onViewLoading(view)