Index: waeup/branches/hraban/src/waeup/basecontainer.py
===================================================================
--- waeup/branches/hraban/src/waeup/basecontainer.py	(revision 3557)
+++ waeup/branches/hraban/src/waeup/basecontainer.py	(revision 3558)
@@ -1,8 +1,10 @@
 import grok
+import os
 from waeup.interfaces import IBaseContainer
 from waeup.baseitem import BaseItem
-from waeup.viewlets import MainArea
+from waeup.viewlets import MainArea, Edit
+from zope.component import getMultiAdapter
 
-class BaseContainer(BaseItem, grok.Container):
+class BaseContainer(grok.Container):
     """
     The base container. This is a stub for now. It can have
@@ -19,9 +21,8 @@
     """
     grok.viewletmanager(MainArea)
-    #grok.context(grok.interfaces.IContainer)
-    
-class Add(grok.AddForm):
-    #form_fields = grok.AutoFields(self.context.childClass)
-#DOESN'T WORK    grok.template("../basecontainer_templates/add.pt")
+
+class AddForm(grok.AddForm):
+    #grok.template('edit_form')
+    template = grok.PageTemplate(filename=os.path.join('basecontainer_templates', 'edit_form.pt'))
 
     def update(self):
@@ -29,7 +30,21 @@
         grok.AddForm.update(self)
 
-    @grok.action('Add Item')
-    def addItem(self, name, *args, **kw):
-        item = self.context.childClass(name=name)
-        self.context[name] = item
-        self.redirect(self.url(item))
+    @grok.action('Add item')
+    def add(self, **data):
+        obj = self.context.childClass(**data)
+        name = data['name'].lower().replace(' ', '_')
+        self.context[name] = obj
+
+class Add(grok.Viewlet):
+    grok.viewletmanager(MainArea)
+    #grok.template('edit_form')
+    grok.context(IBaseContainer)
+    grok.view(Edit)
+
+    def update(self):
+        self.form = getMultiAdapter((self.context, self.request),
+                                    name='addform')
+        self.form.update_form()
+
+    def render(self):
+        return self.form.render()
Index: waeup/branches/hraban/src/waeup/basecontainer_templates/add.pt
===================================================================
--- waeup/branches/hraban/src/waeup/basecontainer_templates/add.pt	(revision 3557)
+++ 	(revision )
@@ -1,72 +1,0 @@
-<html>
-<head>
-  <link rel="stylesheet" type="text/css"
-	tal:attributes="href static/simple.css" />
-</head>
-
-<body>
-    <h1>Add Form</h1>
-<form action="." tal:attributes="action request/URL" method="post"
-      class="edit-form" enctype="multipart/form-data">
-
-  <h1 i18n:translate=""
-    tal:condition="view/label"
-    tal:content="view/label">Label</h1>
-
-  <div class="form-status"
-    tal:define="status view/status"
-    tal:condition="status">
-
-    <div i18n:translate="" tal:content="view/status">
-      Form status summary
-    </div>
-
-    <ul class="errors" tal:condition="view/errors">
-      <li tal:repeat="error view/error_views">
-         <span tal:replace="structure error">Error Type</span>
-      </li>
-    </ul>
-  </div>
-
-  <table class="form-fields">
-    <tbody>
-      <tal:block repeat="widget view/widgets">
-        <tr>
-          <td class="label" tal:define="hint widget/hint">
-            <label tal:condition="python:hint"
-                   tal:attributes="for widget/name">
-              <span class="required" tal:condition="widget/required"
-              >*</span><span i18n:translate=""
-                             tal:content="widget/label">label</span>
-            </label>
-            <label tal:condition="python:not hint"
-                   tal:attributes="for widget/name">
-              <span class="required" tal:condition="widget/required"
-              >*</span><span i18n:translate=""
-                             tal:content="widget/label">label</span>
-            </label>
-          </td>
-          <td class="field">
-            <div class="widget" tal:content="structure widget">
-              <input type="text" />
-            </div>
-            <div class="error" tal:condition="widget/error">
-              <span tal:replace="structure widget/error">error</span>
-            </div>
-          </td>
-        </tr>
-      </tal:block>
-    </tbody>
-  </table>
-
-  <div id="actionsView">
-    <span class="actionButtons" tal:condition="view/availableActions">
-      <input tal:repeat="action view/actions"
-             tal:replace="structure action/render"
-             />
-    </span>
-  </div>
-</form>
-
-</body>
-</html>
Index: waeup/branches/hraban/src/waeup/basecontainer_templates/edit_form.pt
===================================================================
--- waeup/branches/hraban/src/waeup/basecontainer_templates/edit_form.pt	(revision 3557)
+++ waeup/branches/hraban/src/waeup/basecontainer_templates/edit_form.pt	(revision 3558)
@@ -1,5 +1,5 @@
 <form action="." tal:attributes="action request/URL" method="post"
       class="edit-form" enctype="multipart/form-data">
-
+<!-- 
   <h2 i18n:translate=""
     tal:condition="view/label"
@@ -20,4 +20,5 @@
     </ul>
   </div>
+-->
 
   <div class="form-fields">
Index: waeup/branches/hraban/src/waeup/baseitem.py
===================================================================
--- waeup/branches/hraban/src/waeup/baseitem.py	(revision 3557)
+++ waeup/branches/hraban/src/waeup/baseitem.py	(revision 3558)
@@ -1,4 +1,8 @@
+# baseitem.py
+import os
 import grok
-from waeup.viewlets import MainArea
+from waeup.viewlets import MainArea, Edit
+from waeup.interfaces import IBaseItem
+from zope.component import getMultiAdapter
 
 class BaseItem(grok.Model):
@@ -6,13 +10,43 @@
     Base item
     """
-
-class Edit(grok.EditForm):
+    grok.implements(IBaseItem)
     
-    def update(self):
-        self.form_fields = grok.AutoFields(self.context.__class__)
-        grok.EditForm.update(self)
-
 class Content(grok.Viewlet):
     grok.viewletmanager(MainArea)
-    #grok.context(grok.interfaces.IContainer)
+    grok.context(IBaseItem)
 
+
+#class Edit(grok.EditForm):
+#    
+#    def update(self):
+#        self.form_fields = grok.AutoFields(self.context.__class__)
+#        grok.EditForm.update(self)
+
+
+class AddForm(grok.AddForm):
+    #grok.template('edit_form')
+    template = grok.PageTemplate(filename=os.path.join('baseitem_templates', 'edit_form.pt'))
+
+    def update(self):
+        self.form_fields = grok.AutoFields(self.context.childClass)
+        grok.AddForm.update(self)
+
+    @grok.action('Add item')
+    def add(self, **data):
+        obj = self.context.childClass(**data)
+        name = data['name'].lower().replace(' ', '_')
+        self.context[name] = obj
+
+class Add(grok.Viewlet):
+    grok.viewletmanager(MainArea)
+    #grok.template('edit_form')
+    grok.context(IBaseItem)
+    grok.view(Edit)
+
+    def update(self):
+        self.form = getMultiAdapter((self.context, self.request),
+                                    name='addform')
+        self.form.update_form()
+
+    def render(self):
+        return self.form.render()
Index: waeup/branches/hraban/src/waeup/baseitem_templates/content.pt
===================================================================
--- waeup/branches/hraban/src/waeup/baseitem_templates/content.pt	(revision 3557)
+++ waeup/branches/hraban/src/waeup/baseitem_templates/content.pt	(revision 3558)
@@ -1,3 +1,7 @@
-<h1>Object <span tal:replace="context/name"></span></h1>
-  <a href="" tal:attributes="href python:view.url(context.__parent__)">Up</a>
-  <a href="" tal:attributes="href python:view.url(context, 'edit')">Edit</a>
+<div class="menubar">
+	<ul>
+		<li><a href="" tal:attributes="href python:view.url(context.__parent__)">Up</a></li>
+		<li><a href="" tal:attributes="href python:view.url(context, 'edit')">Edit</a></li>
+	</ul>
+</div>
+<h2>Object <span tal:replace="context/name"></span></h2>
Index: waeup/branches/hraban/src/waeup/docs/faq-staff-de.rst
===================================================================
--- waeup/branches/hraban/src/waeup/docs/faq-staff-de.rst	(revision 3557)
+++ waeup/branches/hraban/src/waeup/docs/faq-staff-de.rst	(revision 3558)
@@ -57,4 +57,15 @@
    Hochschulen selbst ausgeführt werden.
 
+Zielgruppe des Portals
+----------------------
+
+Es gibt in Nigeria über 350 Hochschulen, für die das Portal geeignet
+wäre, davon ca. 200 "Fachhochschulen" mit 3000-10.000 Studenten und
+150 Universitäten mit 20.000-70.000 Studenten.
+
+Im Prinzip lässt sich das System auch in allen anderen Ländern einsetzen,
+wo es das Bachelor-/Master-Studiensystem gibt. Hierfür müssten allerdings
+die Workflows und Zahlungsmodalitäten angepasst werden.
+
 Geschäftsmodell
 ---------------
@@ -62,7 +73,4 @@
 WAeUP bekommt einen Anteil an allen Zahlungen, die über das Portal
 abgewickelt werden, etwa 1,20 € pro Student und Jahr.
-Es gibt in Nigeria über 350 Hochschulen, für die das Portal geeignet
-wäre, davon ca. 200 "Fachhochschulen" mit 3000-10.000 Studenten und
-150 Universitäten mit 20.000-70.000 Studenten.
 
 Was ist der derzeitige Status?
Index: waeup/branches/hraban/src/waeup/docs/uli-on-interfaces.txt
===================================================================
--- waeup/branches/hraban/src/waeup/docs/uli-on-interfaces.txt	(revision 3558)
+++ waeup/branches/hraban/src/waeup/docs/uli-on-interfaces.txt	(revision 3558)
@@ -0,0 +1,160 @@
+Mail von Uli Fouquet am 2. Juli 2008:
+
+Am Mittwoch, den 02.07.2008, 11:20 +0200 schrieb Henning Hraban Ramm:
+
+> Habe ich richtig verstanden, dass wir die grundsätzlichen
+> Inhalts-Objekte nur IContainer implementieren lassen statt von einem
+> BaseContainer abzuleiten?
+> Oder beides, so wie beim Inhaltsobjekt (Student erbt von BaseItem und
+> implementiert IStudent)?
+
+Ersteres sollte genügen. Wir sollten allerdings nicht von IContainer
+ableiten, sondern ein eigenes Interface definieren, z.B.
+`IWAeUPContainer` oder so. Das kann am Anfang ein pures Marker-Interface
+sein, also ohne Methoden, Attribute etc., und dann kann man schauen, was
+wir von WAeUP-Containern generell erwarten. Das kann dann ins Interface
+rein.
+
+> Nochmal anders formuliert:
+> Wenn eine Klasse von grok.Container erbt, muss sie dann noch
+> grok.IContainer implementieren?
+
+Sollte sie, aber das ist in diesem Fall eine implizite Angelegenheit, um
+die wir uns nicht zu kümmern brauchen. Die Default-Implementierung
+`grok.Container` sollte das für uns erledigt haben.
+
+Die Sache ist bei uns eher so, dass wir einen mächtigeren Container-Typ
+brauchen, der evtl. noch ein paar zusätzliche Sachen braucht und: wir
+brauchen ein Unterscheidungskriterium, um WAeUP-Container von
+gewöhnlichen Containern zu unterscheiden. Das ist bereits mit einem
+Marker-Interface erledigt.
+
+In gewöhnlicher Objekt-Orientierung macht man das über Klassen und
+Vererbung, so wie das auch im Moment der Fall ist: die Views binden sich
+an Objekte vom Typ `BaseContainer` (oder Ableitungen davon). Die Klasse
+entscheidet.
+
+In einer Komponenten-Architektur binden sich Views aber gern an
+Interfaces, um für unterschiedliche Implementierungen offen zu sein.
+Vielleicht wollen wir irgendwann einen anderen Containertyp bauen, der
+aber das gleiche Interface wie WAeUPContainer implementiert und dann
+sind die Views schonmal wiederverwendbar.
+
+Die StudentContainer etc. können dann von grok.Container ableiten und
+versprechen, IWAeUPContainer zu implementieren und ein Default-View
+würde sich an IWAeUPContainer binden, während ein speziellerer View sich
+weiterhin an StudentContainer binden könnte.
+
+Um auch das Letztere ganz unabhängig von der Implementierung zu machen,
+könnte man zusätzlich ein Interface IStudentContainer von
+IWAeUPContainer ableiten (sowas ist möglich und korrekt), und
+StudentContainer dann dieses implementieren lassen. Views für
+IWAeUPContainer würden sich dann für StudentContainer-Objekte zuständig
+fühlen, sofern nicht ein View existiert, der sich an das ganz
+spezifische Interface IStudentContainer bindet.
+
+<Blah-Schwafel-Sektion>
+
+Die folgende Abschweifung ist nur abstraktes Geschwafel. Wer den
+Oberlehrer-Mode abschalten will, kann weiter unten fortfahren ;-)
+
+Der entscheidende Unterschied in dem ganzen Gewusel ist: in
+herkömmlicher Objekt-Orientierung baut man eine `B ist ein A` Relation
+über Ableitung von Klassen. In einer Komponenten-Architektur dient die
+Ableitung von Klassen aber nur der eigenen Faulheit: um Tipparbeit zu
+sparen (überspitzt gesagt). Die genannte Relation wird vielmehr über
+Interfaces verwirklicht. `B ist ein A` gilt genau dann, wenn B und A
+dasselbe Interface implementieren. Die jeweiligen Klassen (und ihre
+Implementierung) sind dabei piepegal.
+
+Ein inneres Warnsignal sollte bei Euch immer dann Aufleuchten, wenn Ihr
+Klassen ableitet aber in der abgeleiteten Klasse genausoviel Code steht
+wie in der Basisklasse. Z.B.::
+
+ class A(object):
+   name='foo'
+   bar='baz'
+
+ class A2(A):
+   name='braz'
+   bar='buzz'
+
+ class A3(A):
+   name='bruzz'
+   bar='bla'
+
+Da fragt man sich schnell, was die Ableitung gebracht hat. In einer CA
+(Component Architecture) sähe das so aus:
+
+  from zope.interface import Interface, implements, Attribute
+  class IA(Interface):
+    name = Attribute()
+    bar = Attribute()
+
+  class A2(object):
+    implements(IA)
+    name='foo'
+    bar='baz'
+
+  class A3(object):
+    implements(IA)
+    name='bruzz'
+    bar='bla'
+
+Das sieht zwar sehr ähnlich aus, hat aber entscheidende Vorteile, sobald
+wir eine zusätzliche Funktionalität wollen. Nehmen wir mal die
+Möglichkeit,  zu im- oder exportieren. Das ist eine andere
+Funktionalität als, nun ja, A-isch zu sein. Wir erwarten klare Dinge von
+einem Importer/Exporter::
+
+ class IImportableExportable(Interface):
+   def export():
+       """Delivers all content as CSV data.
+       """
+
+   def import(data):
+       """Stores the data.
+
+       Data is expected to be a list of rows of a CSV file.
+       """
+
+Wie stellen wir aber Importer-/Exporter-Funktionalität in einer
+Klassenhierarchie dar (wenn wir kurz zum ersten Beispiel ohne Interfaces
+zurückkehren)? Wir würden wohl die entsprechenden Methoden `import` und
+`export` in der Basisklasse implementieren, ohne große Hoffnung, dass
+irgendeine abgeleitete Klasse diese Implementierung gebrauchen könnte.
+Vielleicht lassen wir sie deshalb lieber gleich ganz weg. Hier fängt's
+mit dem herkömmlichen Ansatz an,  haarig zu werden.
+
+Mit Interfaces können wir hingegen einen Adapter schreiben, der uns
+einen Importer/Exporter für spezielle Interfaces zur Verfügung stellt.
+Wir könnten auch in unseren Container-Klassen direkt die entsprechenden
+Methoden entwickeln und sie (zusätzlich) als `IImportableExportable`
+registrieren lassen. Egal, wie wir das dann machen: wir haben ein
+abstraktes Framework zur Hand, dass uns erlaubt, solche Funktionalitäten
+getrennt voneinander zu behandeln. Ein View kann z.B. über Abfrage der
+Interfaces überprüfen, ob er für sein Context-Objekt einen
+Import/Export-Link zur Verfügung stellen soll, etc. Das ist nett würde
+ich sagen, und gelebte Komponenten-Architektur :-)
+
+Das sollte nur ein kleiner Anhang zu versäumten Themen auf dem Workshop
+sein.
+
+</Blah-Schwafel-Sektion>
+
+> Ist es weiterhin sinnvoll, zwischen BaseContainer (IContainer) und
+> BaseItem (IModel gibt's nicht - was anderes?) zu unterscheiden, so
+> dass wir z.B. StudentsContainer und Student haben? (Ich nehme an ja,
+> aber das mag in Zope 3 anders sein...)
+
+Das ist bestimmt sinnvoll. Container sind was anderes als Item-Objekte.
+Sie bieten eine unterschiedliche Funktionalität also sollten da auch
+unterschiedliche Interfaces existieren. Auch hier können (sollten) wir
+eigene Interfaces bauen. Das Gegenstück zu IContainer ist übrigens
+IContained. Aber wir brauchen eigentlich beides nicht.
+
+> Auch wenn das letztendlich ein Berufenerer ausführt, will ich's mal
+> selber machen, um die Zusammenhänge besser zu verstehen.
+
+Klar, hau rein! Ist nicht ganz trivial, was Du da vorhast, aber bestimmt
+gut zum Lernen. Vielleicht hilft mein Gelaber oben ja ein bischen dabei.
Index: waeup/branches/hraban/src/waeup/interfaces.py
===================================================================
--- waeup/branches/hraban/src/waeup/interfaces.py	(revision 3557)
+++ waeup/branches/hraban/src/waeup/interfaces.py	(revision 3558)
@@ -4,13 +4,4 @@
 #from zope.interface import Interface
 from zope import schema
-
-class IUniversity(grok.interfaces.IContainer):
-    """Representation of a university.
-    """
-    name = schema.TextLine(
-        title = u'Name of University',
-        default = u'Unnamed',
-        required = True,
-        )
 
 class IBaseContainer(grok.interfaces.IContainer):
@@ -21,2 +12,14 @@
         )
     
+
+class IBaseItem(IBaseContainer):
+    pass
+
+class IUniversity(IBaseContainer):
+    """Representation of a university.
+    """
+    name = schema.TextLine(
+        title = u'Name of University',
+        default = u'Unnamed',
+        required = True,
+        )
Index: waeup/branches/hraban/src/waeup/static/app.css
===================================================================
--- waeup/branches/hraban/src/waeup/static/app.css	(revision 3557)
+++ waeup/branches/hraban/src/waeup/static/app.css	(revision 3558)
@@ -99,4 +99,5 @@
 	border: 1px solid #005500;
 	border-bottom: none;
+	margin-left: 0.5em;
 }
 
@@ -108,4 +109,8 @@
 	color: black;
 	text-decoration: none;
+}
+
+.menubar ul li a:active {
+	font-weight: bold;
 }
 
Index: waeup/branches/hraban/src/waeup/students/interfaces.py
===================================================================
--- waeup/branches/hraban/src/waeup/students/interfaces.py	(revision 3557)
+++ waeup/branches/hraban/src/waeup/students/interfaces.py	(revision 3558)
@@ -3,6 +3,7 @@
 import grok
 from zope import schema
+from waeup.interfaces import IBaseItem
 
-class IStudent(grok.interfaces.IContainer):
+class IStudent(IBaseItem):
     """Representation of a student.
     """
Index: waeup/branches/hraban/src/waeup/viewlets.py
===================================================================
--- waeup/branches/hraban/src/waeup/viewlets.py	(revision 3557)
+++ waeup/branches/hraban/src/waeup/viewlets.py	(revision 3558)
@@ -14,4 +14,10 @@
     def __init__(self, context, request):#
         super(Index, self).__init__(context, request)
+    
+    def getSite(self):
+        return grok.getSite()
+
+class Edit(Index):
+    pass
 
 class Head(grok.ViewletManager):
@@ -41,7 +47,4 @@
     grok.viewletmanager(Header)
     grok.order(2)
-    
-    def getSite(self):
-        return grok.getSite()
 
 class LeftSidebar(grok.ViewletManager):
Index: waeup/branches/hraban/src/waeup/viewlets_templates/logo.pt
===================================================================
--- waeup/branches/hraban/src/waeup/viewlets_templates/logo.pt	(revision 3557)
+++ waeup/branches/hraban/src/waeup/viewlets_templates/logo.pt	(revision 3558)
@@ -1,4 +1,4 @@
-<div id="logo">
+<div id="logo" tal:define="app view/getSite">
     <img tal:attributes="src static/logo_waeup.gif" alt="WAeUp logo" />
-    <h1 tal:content="context/name">Sample University</h1>
+    <h1 tal:content="app/name">Sample University</h1>
 </div>
Index: waeup/branches/hraban/src/waeup/viewlets_templates/navigationbar.pt
===================================================================
--- waeup/branches/hraban/src/waeup/viewlets_templates/navigationbar.pt	(revision 3557)
+++ waeup/branches/hraban/src/waeup/viewlets_templates/navigationbar.pt	(revision 3558)
@@ -1,4 +1,4 @@
 <div id="adminbar" class="menubar"
-    tal:define="app viewlet/getSite">
+    tal:define="app view/getSite">
 <!--	<ul>
 		<tal:block  tal:repeat="menuitem view/menuitems">
