diff --git a/compound/book/__init__.py b/compound/book/__init__.py
new file mode 100644
index 0000000..8c1a40c
--- /dev/null
+++ b/compound/book/__init__.py
@@ -0,0 +1,2 @@
+# __init__.py
+# Package: loops.compound.book
diff --git a/compound/book/base.py b/compound/book/base.py
new file mode 100644
index 0000000..80579fe
--- /dev/null
+++ b/compound/book/base.py
@@ -0,0 +1,52 @@
+#
+# Copyright (c) 2012 Helmut Merz helmutm@cy55.de
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+"""
+Implementation of book and book components
+"""
+
+from zope.cachedescriptors.property import Lazy
+from zope.interface import implements
+from zope.traversing.api import getName
+
+from loops.compound.base import Compound
+from loops.compound.book.interfaces import IPage
+from loops.type import TypeInterfaceSourceList
+
+
+TypeInterfaceSourceList.typeInterfaces += (IPage,)
+
+
+class Page(Compound):
+
+ implements(IPage)
+
+ compoundPredicateNames = ['ispartof', 'standard']
+
+ @Lazy
+ def documentType(self):
+ return self.context.getConceptManager()['documenttype']
+
+ def getParts(self):
+ result = {}
+ for r in super(Page, self).getParts():
+ for parent in r.getParents():
+ if parent.conceptType == self.documentType:
+ item = result.setdefault(getName(parent), [])
+ item.append(r)
+ return result
diff --git a/compound/book/browser.py b/compound/book/browser.py
new file mode 100644
index 0000000..a293839
--- /dev/null
+++ b/compound/book/browser.py
@@ -0,0 +1,71 @@
+#
+# Copyright (c) 2012 Helmut Merz helmutm@cy55.de
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+"""
+View class(es) book/section/page structures.
+"""
+
+from cgi import parse_qs
+from zope import interface, component
+from zope.app.pagetemplate import ViewPageTemplateFile
+from zope.cachedescriptors.property import Lazy
+
+from cybertools.typology.interfaces import IType
+from loops.browser.lobo import standard
+from loops.browser.concept import ConceptRelationView as BaseConceptRelationView
+from loops.browser.resource import ResourceView as BaseResourceView
+from loops.common import adapted, baseObject
+
+
+standard_template = standard.standard_template
+book_template = ViewPageTemplateFile('view_macros.pt')
+
+
+class PageLayout(standard.Layout):
+
+ def getParts(self):
+ parts = ['headline', 'keyquestions', 'maintext',
+ 'story', 'usecase', 'quote']
+ return self.getPartViews(parts)
+
+
+class PagePart(object):
+
+ template = book_template
+ templateName = 'compound.book'
+ macroName = 'text'
+ partName = None # define in subclass
+ gridPattern = ['span-4']
+
+ def getResources(self):
+ result = []
+ res = self.adapted.getParts().get(self.partName) or []
+ for idx, r in enumerate(res):
+ result.append(standard.ResourceView(
+ r, self.request, parent=self, idx=idx))
+ return result
+
+
+class Headline(PagePart, standard.Header2):
+
+ macroName = 'headline'
+
+
+class MainText(PagePart, standard.BasePart):
+
+ partName = 'maintext'
diff --git a/compound/book/configure.zcml b/compound/book/configure.zcml
new file mode 100644
index 0000000..fe63f85
--- /dev/null
+++ b/compound/book/configure.zcml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/compound/book/interfaces.py b/compound/book/interfaces.py
new file mode 100644
index 0000000..3dd1e43
--- /dev/null
+++ b/compound/book/interfaces.py
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2012 Helmut Merz helmutm@cy55.de
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+"""
+Books, sections, pages...
+"""
+
+from zope.interface import Interface, Attribute
+from zope import interface, component, schema
+
+from loops.compound.interfaces import ICompound
+from loops.util import _
+
+
+class IPage(ICompound):
+
+ pass
diff --git a/compound/book/view_macros.pt b/compound/book/view_macros.pt
new file mode 100644
index 0000000..7e3a6f3
--- /dev/null
+++ b/compound/book/view_macros.pt
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+