Make typeProvider attribute available for concepts

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1130 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2006-03-19 09:49:47 +00:00
parent c33f952ce7
commit 7622600c99
7 changed files with 115 additions and 13 deletions

View file

@ -125,12 +125,23 @@ class NodeView(BaseView):
return [NodeView(child, self.request) return [NodeView(child, self.request)
for child in self.context.getMenuItems()] for child in self.context.getMenuItems()]
@Lazy
def parents(self):
return zapi.getParents(self.context)
@Lazy
def nearestMenuItem(self):
if self.context.isMenuItem():
return self.context
for p in self.parents:
if p.isMenuItem():
return p
def selected(self, item): def selected(self, item):
if item.context == self.context: return item.context == self.nearestMenuItem
return True
if item.context in zapi.getParents(self.context) and not item.menuItems: def active(self, item):
return True return item.context == self.context or item.context in self.parents
return False
def targetDefaultView(self): def targetDefaultView(self):
target = self.request.annotations.get('loops.view', {}).get('target') target = self.request.annotations.get('loops.view', {}).get('target')
@ -149,6 +160,7 @@ class NodeView(BaseView):
if target is not None: if target is not None:
return zapi.getUtility(IIntIds).getId(target) return zapi.getUtility(IIntIds).getId(target)
class ConfigureView(NodeView): class ConfigureView(NodeView):
""" An editing view for configuring a node, optionally creating """ An editing view for configuring a node, optionally creating
a target object. a target object.

View file

@ -28,6 +28,7 @@ from zope.app.container.contained import Contained
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from zope.component import adapts from zope.component import adapts
from zope.interface import implements from zope.interface import implements
from zope.interface import alsoProvides, directlyProvides, directlyProvidedBy
from zope import schema from zope import schema
from zope.security.proxy import removeSecurityProxy from zope.security.proxy import removeSecurityProxy
from persistent import Persistent from persistent import Persistent
@ -36,7 +37,7 @@ from cybertools.relation import DyadicRelation
from cybertools.relation.registry import getRelations from cybertools.relation.registry import getRelations
from cybertools.relation.registry import getRelationSingle, setRelationSingle from cybertools.relation.registry import getRelationSingle, setRelationSingle
from cybertools.relation.interfaces import IRelationRegistry, IRelatable from cybertools.relation.interfaces import IRelationRegistry, IRelatable
from cybertools.typology.interfaces import ITypeManager from cybertools.typology.interfaces import IType, ITypeManager
from interfaces import IConcept, IConceptRelation, IConceptView from interfaces import IConcept, IConceptRelation, IConceptView
from interfaces import IConceptManager, IConceptManagerContained from interfaces import IConceptManager, IConceptManagerContained

View file

@ -240,6 +240,8 @@
<adapter factory="loops.type.ResourceType" /> <adapter factory="loops.type.ResourceType" />
<adapter factory="loops.type.LoopsTypeManager" /> <adapter factory="loops.type.LoopsTypeManager" />
<adapter factory="loops.type.TypeConcept" />
<adapter factory="loops.external.NodesLoader" /> <adapter factory="loops.external.NodesLoader" />
<adapter factory="loops.external.NodesExporter" /> <adapter factory="loops.external.NodesExporter" />
<adapter factory="loops.external.NodesImporter" /> <adapter factory="loops.external.NodesImporter" />

View file

@ -190,3 +190,40 @@ condition:
>>> sorted(t.token for t in types) >>> sorted(t.token for t in types)
['loops.resource.Document', 'loops.resource.MediaAsset'] ['loops.resource.Document', 'loops.resource.MediaAsset']
Type-based interfaces
---------------------
A type has an optional typeInterface attribute that objects of this type
will be adaptable to. The default for this is None:
>>> cc1_type.typeInterface is None
True
For concept objects that provide types (type providers) the value of
the typeInterface attribute is the ITypeConcept interface:
>>> from loops.interfaces import ITypeConcept
>>> topic_type.typeInterface is ITypeConcept
True
We now want to have a topic (i.e. a concept that has topic_type as its type)
to provide the interface ITopic. This is done by assigning this interface
to topic_type.typeProvider, i.e. the 'topic' concept, via an adapter:
>>> from loops.type import TypeConcept
>>> ztapi.provideAdapter(IConcept, ITypeConcept, TypeConcept)
>>> class ITopic(Interface): pass
>>> from zope.interface import implements
>>> class Topic(object):
... implements(ITopic)
... def __init__(self, context): pass
>>> ztapi.provideAdapter(IConcept, ITopic, Topic)
>>> ITypeConcept(topic).typeInterface = ITopic
>>> cc1.conceptType = topic
>>> cc1_type = IType(cc1)
>>> cc1Adapter = cc1_type.typeInterface(cc1)
>>> ITopic.providedBy(cc1Adapter)
True

View file

@ -384,6 +384,10 @@ class INode(IView, IBaseNode):
a menu). a menu).
""" """
def isMenuItem():
""" Return True if this object is a menu item.
"""
def getTextItems(): def getTextItems():
""" Return the text items belonging to this object. """ Return the text items belonging to this object.
""" """
@ -465,3 +469,13 @@ class IIndexAttributes(Interface):
""" Return a string that identifies the type of the object. """ Return a string that identifies the type of the object.
""" """
# types stuff
class ITypeConcept(Interface):
""" This interface should be provided by concepts of type 'type'.
"""
typeInterface = Attribute('The interface provided by objects of this type')

30
type.py
View file

@ -24,10 +24,12 @@ $Id$
from zope.app import zapi from zope.app import zapi
from zope.component import adapts from zope.component import adapts
from zope.interface import implements
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from zope.dottedname.resolve import resolve from zope.dottedname.resolve import resolve
from cybertools.typology.type import BaseType, TypeManager from cybertools.typology.type import BaseType, TypeManager
from loops.interfaces import ILoopsObject, IConcept, IResource from loops.interfaces import ILoopsObject, IConcept, IResource
from loops.interfaces import ITypeConcept
from loops.concept import Concept from loops.concept import Concept
from loops.resource import Document, MediaAsset from loops.resource import Document, MediaAsset
@ -72,6 +74,17 @@ class ConceptType(LoopsType):
def defaultContainer(self): def defaultContainer(self):
return self.root.getConceptManager() return self.root.getConceptManager()
@Lazy
def typeInterface(self):
adapter = zapi.queryAdapter(self.typeProvider, ITypeConcept)
if adapter is not None:
return adapter.typeInterface
else:
conceptType = self.context.conceptType
if conceptType is conceptType.getConceptManager().getTypeConcept():
return ITypeConcept
return None
class ConceptTypeInfo(ConceptType): class ConceptTypeInfo(ConceptType):
@ -161,3 +174,20 @@ class LoopsTypeManager(TypeManager):
def resourceTypes(self): def resourceTypes(self):
return tuple([ResourceTypeInfo(self.context, cls) return tuple([ResourceTypeInfo(self.context, cls)
for cls in (Document, MediaAsset)]) for cls in (Document, MediaAsset)])
class TypeConcept(object):
implements(ITypeConcept)
adapts(IConcept)
def __init__(self, context):
self.context = context
def getTypeInterface(self):
return getattr(self.context, '_typeInterface', None)
def setTypeInterface(self, ifc):
self.context._typeInterface = ifc
typeInterface = property(getTypeInterface, setTypeInterface)

12
view.py
View file

@ -128,7 +128,9 @@ class Node(View, OrderedContainer):
continue continue
def getMenu(self): def getMenu(self):
return self.nodeType == 'menu' and self or self.getParentNode(['menu']) if self.nodeType == 'menu':
return self
return self.getParentNode(['menu'])
def getPage(self): def getPage(self):
pageTypes = ['page', 'menu', 'info'] pageTypes = ['page', 'menu', 'info']
@ -142,6 +144,9 @@ class Node(View, OrderedContainer):
def getTextItems(self): def getTextItems(self):
return self.getChildNodes(['text']) return self.getChildNodes(['text'])
def isMenuItem(self):
return self.nodeType in ('page', 'menu')
class ViewManager(OrderedContainer): class ViewManager(OrderedContainer):
@ -171,10 +176,11 @@ class NodeTraverser(ItemTraverser):
return self.context.getLoopsRoot() return self.context.getLoopsRoot()
if name.startswith('.target'): if name.startswith('.target'):
if len(name) > len('.target'): if len(name) > len('.target'):
idx = int(name[len('.target'):]) uid = int(name[len('.target'):])
target = zapi.getUtility(IIntIds).getObject(idx) target = zapi.getUtility(IIntIds).getObject(uid)
else: else:
target = self.context.target target = self.context.target
if target is not None:
viewAnnotations = request.annotations.get('loops.view', {}) viewAnnotations = request.annotations.get('loops.view', {})
viewAnnotations['target'] = target viewAnnotations['target'] = target
request.annotations['loops.view'] = viewAnnotations request.annotations['loops.view'] = viewAnnotations