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)
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):
if item.context == self.context:
return True
if item.context in zapi.getParents(self.context) and not item.menuItems:
return True
return False
return item.context == self.nearestMenuItem
def active(self, item):
return item.context == self.context or item.context in self.parents
def targetDefaultView(self):
target = self.request.annotations.get('loops.view', {}).get('target')
@ -149,6 +160,7 @@ class NodeView(BaseView):
if target is not None:
return zapi.getUtility(IIntIds).getId(target)
class ConfigureView(NodeView):
""" An editing view for configuring a node, optionally creating
a target object.

View file

@ -28,6 +28,7 @@ from zope.app.container.contained import Contained
from zope.cachedescriptors.property import Lazy
from zope.component import adapts
from zope.interface import implements
from zope.interface import alsoProvides, directlyProvides, directlyProvidedBy
from zope import schema
from zope.security.proxy import removeSecurityProxy
from persistent import Persistent
@ -36,7 +37,7 @@ from cybertools.relation import DyadicRelation
from cybertools.relation.registry import getRelations
from cybertools.relation.registry import getRelationSingle, setRelationSingle
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 IConceptManager, IConceptManagerContained

View file

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

View file

@ -190,3 +190,40 @@ condition:
>>> sorted(t.token for t in types)
['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).
"""
def isMenuItem():
""" Return True if this object is a menu item.
"""
def getTextItems():
""" 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.
"""
# 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.component import adapts
from zope.interface import implements
from zope.cachedescriptors.property import Lazy
from zope.dottedname.resolve import resolve
from cybertools.typology.type import BaseType, TypeManager
from loops.interfaces import ILoopsObject, IConcept, IResource
from loops.interfaces import ITypeConcept
from loops.concept import Concept
from loops.resource import Document, MediaAsset
@ -72,6 +74,17 @@ class ConceptType(LoopsType):
def defaultContainer(self):
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):
@ -161,3 +174,20 @@ class LoopsTypeManager(TypeManager):
def resourceTypes(self):
return tuple([ResourceTypeInfo(self.context, cls)
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)

20
view.py
View file

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