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:
parent
c33f952ce7
commit
7622600c99
7 changed files with 115 additions and 13 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" />
|
||||
|
|
37
helpers.txt
37
helpers.txt
|
@ -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
|
||||
|
|
|
@ -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
30
type.py
|
@ -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
20
view.py
|
@ -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)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue