[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/OFS/Folder/Views/Browser - FolderAdder.py:1.1.2.1 FolderContents.py:1.1.2.1 FolderLimitEdit.py:1.1.2.1 LoadedFolderContents.py:1.1.2.1 __init__.py:1.1.2.1 add.pt:1.1.2.1 add_confirmed.pt:1.1.2.1 browser.zcml:1.1.2.1 contents.pt:1.1.2.1 limit.pt:1.1.2.1 loaded_folder_contents.pt:1.1.2.1 remove_confirmed.pt:1.1.2.1

Stephan Richter srichter@cbu.edu
Fri, 1 Mar 2002 01:37:11 -0500


Update of /cvs-repository/Zope3/lib/python/Zope/App/OFS/Folder/Views/Browser
In directory cvs.zope.org:/tmp/cvs-serv10334/Folder/Views/Browser

Added Files:
      Tag: srichter-OFS_Formulator-branch
	FolderAdder.py FolderContents.py FolderLimitEdit.py 
	LoadedFolderContents.py __init__.py add.pt add_confirmed.pt 
	browser.zcml contents.pt limit.pt loaded_folder_contents.pt 
	remove_confirmed.pt 
Log Message:
Okay, I am finally ready to check this stuff in:

- Reorganized the internal directory structure of every content object. For
  each content object you have now a Views directory that contains further
  directories for different protocols, such as Browser (HTML), XUL, FTP ...

  Note: None of the directories is file-type, but functionality-based. It 
        is a bad idea to create directories for a particular file type, as
        it was common in Zope 2.

- Made Folder, File and Image forms Formulator-based. This allows us now to
  create forms for new protocols. such as XUL very quickly (often just a
  few lines of code). More to Formulator when it is being checked in.

- Cleaned up most files. Almost all files should have now the correct 
  license disclaimer.

- A new object called LoadedFolder was added. LoadedFolder currently 
  provides two new functionalities to folders:
    1. Ordering. You can change the order of the objects. This idea was 
       taking from the Zope 2 product OrderedFolders.
    2. Limit. You can specify the maximal amount of items the folder is 
       allowed to store. This idea was also taken from OrderedFolders.

  Note: Due to much rearranging during this development, there are no tests
        yet written for this. This needs to be done, before we merge with
        the Zoep-3x-branch again.

- Started XUL implementation of screens.

- Fixed some bugs I found lying around.


=== Added File Zope3/lib/python/Zope/App/OFS/Folder/Views/Browser/FolderAdder.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. 
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
# 
##############################################################################
"""
    Define adder component for folders.

$Id: FolderAdder.py,v 1.1.2.1 2002/03/01 06:37:09 srichter Exp $
"""


import os

from Zope.Publisher.Browser.AttributePublisher import AttributePublisher
from Zope.Publisher.Browser.IBrowserPublisher import IBrowserPublisher
from Zope.PageTemplate.PageTemplateFile import PageTemplateFile
from Zope.App.ZMI.Addable import ContentAddables
from Zope.ComponentArchitecture import createObject

class FolderAdderError( Exception ):
    pass

class DuplicateIDError( FolderAdderError ):
    pass

class FolderAdder( AttributePublisher ):

    __implements__ = AttributePublisher.__implements__
    
    def __init__( self, folder ):
        self._folder = folder


    def _listAddables( self ):
        """
            Derived classes override this to change the registry
            in which factories are looked up.
        """
        return ContentAddables.getAddables( self._folder )

    def listAddableInfo( self ):
        """
            Return a sequence of mappings for the addables for our
            folder.
        """
        return self._listAddables()

    def action( self, id, type_name, REQUEST=None):
        """
            Instantiate an object and put it in our folder.
        """
        if id in self._folder.objectIds():
            raise DuplicateIDError, "ID '%s' already in use." % id
        self._folder.setObject( id, createObject( self._folder, type_name ) )

        # XXX:  This is horribly broken, but I can't do better until
        #       we have a way to compute absolute URLs.
        if REQUEST is not None:
            # for unit tests
            REQUEST['RESPONSE'].redirect(REQUEST['URL2'])
        return self.confirmed( type_name=type_name, id=id )


    #
    #   Make it possible for 'index' to find the folder.
    #
    def getContext( self ):
        return self._folder

    index = PageTemplateFile('add.pt')
    confirmed = PageTemplateFile('add_confirmed.pt')


=== Added File Zope3/lib/python/Zope/App/OFS/Folder/Views/Browser/FolderContents.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. 
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
# 
##############################################################################
"""
    Define view component for folder contents.

$Id: FolderContents.py,v 1.1.2.1 2002/03/01 06:37:09 srichter Exp $
"""

import os

from Zope.Publisher.Browser.AttributePublisher import AttributePublisher
from Zope.Publisher.Browser.IBrowserPublisher import IBrowserPublisher
from Zope.PageTemplate.PageTemplateFile import PageTemplateFile
from Zope.App.Service.ServiceManager import ServiceManager

class FolderContents( AttributePublisher ):

    __implements__ = AttributePublisher.__implements__
    
    def __init__( self, folder ):
        self._folder = folder


    def _extractContentInfo( self, item ):
        info = {}
        info['id'] = item[0]
        info['object'] = item[1]

        # XXX:  We will fake this stuff out for now
        info[ 'title' ] = info[ 'url' ] = item[0]
        info['icon'] = None

        return info


    def removeObjects(self, ids, REQUEST=None):
        """ """
        for id in ids:
            self.remove(id)

        # XXX:  This is horribly broken, but I can't do better until
        #       we have a way to compute absolute URLs.
        if REQUEST is not None:
            # for unit tests
            REQUEST['RESPONSE'].redirect(REQUEST['URL1'])
        return self.confirmRemoved()
    

    def remove( self, name, silent=0 ):
        """
            Remove the object stored under 'name', or raise a KeyError
            if no such object (pass non-zero 'silent' to suppress the
            exception).
        """
        try:
            self.getContext().delObject( name )
        except KeyError:
            if not silent:
                raise
        return self.confirmRemoved( name=name )

    def listContentInfo( self ):
        
        return map( self._extractContentInfo, self._folder.objectItems() )

    def addServiceManager(self, REQUEST=None):
        """Create a service manager then add it to the folder."""

        sm = ServiceManager()
        if self.getContext().hasServiceManager():
            raise 'HasServiceManager', (
                  'This folder already contains a service manager')
        self.getContext().setServiceManager(sm)
        if REQUEST is not None:
            return self.index(REQUEST)

    #
    #   Make it possible for 'index' to find the folder.
    #
    def getContext( self ):
        return self._folder

    index = PageTemplateFile('contents.pt')
    confirmRemoved = PageTemplateFile('remove_confirmed.pt')


=== Added File Zope3/lib/python/Zope/App/OFS/Folder/Views/Browser/FolderLimitEdit.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. 
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
# 
##############################################################################
"""

$Id: FolderLimitEdit.py,v 1.1.2.1 2002/03/01 06:37:09 srichter Exp $
"""

from Zope.App.Formulator.Form import Form
from Zope.PageTemplate.PageTemplateFile import PageTemplateFile


class FolderLimitEdit(Form):

    __implements__ = (Form.__implements__,)

    name = 'limitForm'     
    title = 'Folder Item Limit Form'
    description = ('This edit form allows you to ...')

    _fieldViewNames = ['LimitFieldView']

    template = PageTemplateFile('limit.pt')  


class FolderLimitXULEdit(Form):

    __implements__ = (Form.__implements__,)

    name = 'limitForm'     
    title = 'Folder Item Limit Form'
    description = ('This edit form allows you to ...')

    _fieldViewNames = ['XULLimitFieldView']

    template = PageTemplateFile('limit_xul.pt')


=== Added File Zope3/lib/python/Zope/App/OFS/Folder/Views/Browser/LoadedFolderContents.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. 
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
# 
##############################################################################
"""
    Define view component for loaded folder contents.

$Id: LoadedFolderContents.py,v 1.1.2.1 2002/03/01 06:37:09 srichter Exp $
"""

import os

from Zope.Publisher.Browser.AttributePublisher import AttributePublisher
from Zope.Publisher.Browser.IBrowserPublisher import IBrowserPublisher
from Zope.PageTemplate.PageTemplateFile import PageTemplateFile

class LoadedFolderContents( AttributePublisher ):

    __implements__ = AttributePublisher.__implements__
    
    def __init__( self, folder ):
        self._folder = folder


    def _extractContentInfo( self, item ):
        info = {}
        info['id'] = item[0]
        info['object'] = item[1]

        # XXX:  We will fake this stuff out for now
        info[ 'title' ] = info[ 'url' ] = item[0]
        info['icon'] = None

        return info


    def removeObjects( self, ids, REQUEST=None ):
        """ """
        for id in ids:
            self.remove(id)

        # XXX:  This is horribly broken, but I can't do better until
        #       we have a way to compute absolute URLs.
        if REQUEST is not None:
            # for unit tests
            REQUEST['RESPONSE'].redirect(REQUEST['URL1'])
        return self.confirmRemoved()
    

    def remove( self, name, silent=0 ):
        """
            Remove the object stored under 'name', or raise a KeyError
            if no such object (pass non-zero 'silent' to suppress the
            exception).
        """
        try:
            self.getContext().delObject( name )
        except KeyError:
            if not silent:
                raise
        return self.confirmRemoved( name=name )


    def listContentInfo( self ):        
        return map( self._extractContentInfo, self._folder.objectItems() )


    # OrderedFolder functionality

    def moveObjectsUp(self, ids, REQUEST = None):
        '''See interface IOrderedContainer'''
        self.getContext().moveObjectsUp(ids)

        if REQUEST is not None:
            # for unit tests
            REQUEST['RESPONSE'].redirect(REQUEST['URL1'])


    def moveObjectsDown(self, ids, REQUEST = None):
        '''See interface IOrderedContainer'''
        self.getContext().moveObjectsDown(ids)

        if REQUEST is not None:
            # for unit tests
            REQUEST['RESPONSE'].redirect(REQUEST['URL1'])


    def moveObjectsToTop(self, ids, REQUEST = None):
        '''See interface IOrderedContainer'''
        self.getContext().moveObjectsToTop(ids)

        if REQUEST is not None:
            # for unit tests
            REQUEST['RESPONSE'].redirect(REQUEST['URL1'])


    def moveObjectsToBottom(self, ids, REQUEST = None):
        '''See interface IOrderedContainer'''
        self.getContext().moveObjectsToBottom(ids)

        if REQUEST is not None:
            # for unit tests
            REQUEST['RESPONSE'].redirect(REQUEST['URL1'])



    #
    #   Make it possible for 'index' to find the folder.
    #
    def getContext( self ):
        return self._folder

    index = PageTemplateFile( 'loaded_folder_contents.pt' )
    confirmRemoved = PageTemplateFile( 'remove_confirmed.pt' )


=== Added File Zope3/lib/python/Zope/App/OFS/Folder/Views/Browser/__init__.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors. 
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
# 
##############################################################################
"""

$Id: __init__.py,v 1.1.2.1 2002/03/01 06:37:09 srichter Exp $
"""


=== Added File Zope3/lib/python/Zope/App/OFS/Folder/Views/Browser/add.pt ===
<html metal:use-macro="views/standard_macros/page">
<head>
<style metal:fill-slot="headers" type="text/css">
.TypeListing {
    width: 100%;
}

.Selector {
    width: 10px;
}

.TypeIcon {
    width: 20px;
}

.TypeName {
    text-align: left;
}

.TypeDescription {
    text-align: left;
    font-style: italic;
}
</style>
</head>
<body>

<div metal:fill-slot="body">

<form action="action.html" method="POST">
<table class="TypeListing">

  <caption>Add Content To Folder</caption>

    <tr>
      <td class="Selector"><br /></td>
      <th class="TypeName">Title</th>
    </tr>

    <!--
      ** listAddableInfo returns a sequence of mappings, containing:
      **   'id'    : the ID of the addable type
      **   'title' : the title of the addable type
      **   'desc'  : the description of the addable type
      **   'icon'  : the absolute URL of the icon, for the addable type
                     (may be None)
      -->
    <tbody tal:repeat="info container/listAddableInfo">

    <tr>

      <td class="Selector">
        <input type="radio" name="type_name"
               tal:attributes="value info/id; id info/id" />
      </td>

      <td class="TypeName">
        <label tal:attributes="for info/id">
          <img alt="Folder" src="../../ZMI/www/folder_icon.gif"
               tal:condition="info/icon"
               tal:attributes="src info/icon" />
          <span tal:replace="info/title">Folder</span>
        </label>
      </td>

    </tr>

    <tr>
      <td class="Selector"><br /></td>
      <td class="TypeDescription" tal:content="info/description">
          Folders are generic containers for content, including other
          folders.
      </td>
    </tr>

  </tbody>

  <tbody tal:condition="nothing">

    <tr>

      <td class="Selector">
        <input type="radio" name="type_name" value="" />
               
      </td>

      <td class="TypeName">
        <img alt="Folder" src="../../ZMI/www/document_icon.gif" />
        Document
      </td>

    </tr>

    <tr>
      <td class="Selector"><br /></td>
      <td class="TypeDescription">
          Documents are simple textual content.
      </td>
    </tr>

  </tbody>

  <tr>
    <td><br/></td>
    <td><input type="text" name="id" />
        <input type="submit" value=" Add " />
    </td>
  </tr>

</table>
</form>
</div>
</body>
</html>


=== Added File Zope3/lib/python/Zope/App/OFS/Folder/Views/Browser/add_confirmed.pt ===
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<!--
      metal:use-macro="presentation/standard_macros/html">
  -->
<body>

<p> Object added successfully. </p>

</body>
</html>


=== Added File Zope3/lib/python/Zope/App/OFS/Folder/Views/Browser/browser.zcml ===
<zopeConfigure
   xmlns='http://namespaces.zope.org/zope'
   xmlns:security='http://namespaces.zope.org/security'
   xmlns:browser='http://namespaces.zope.org/browser'
>

  <!-- Folder View Directives -->

  <browser:defaultView name="contents"
    for="Zope.App.OFS.Folder.Folder.IFolder."
    factory="Zope.App.OFS.Folder.Views.Browser.FolderContents." />

  <security:protectClass 
    name="Zope.App.OFS.Folder.Views.Browser.FolderContents."
    permission_id="Zope.ManageContent" 
    methods="index, listContentInfo, remove, removeObjects, confirmRemoved, addServiceManager"/>
     
  <browser:view name="adder"
    for="Zope.App.OFS.Folder.Folder.IFolder."
    factory="Zope.App.OFS.Folder.Views.Browser.FolderAdder." />

  <security:protectClass 
    name="Zope.App.OFS.Folder.Views.Browser.FolderAdder."
    permission_id="Zope.ManageContent" 
    methods="index, confirmed, action, listAddableInfo" />


  <!-- Loaded Folder View Directives -->

  <browser:defaultView name="contents"
    for="Zope.App.OFS.Folder.LoadedFolder.ILoadedFolder."
    factory="Zope.App.OFS.Folder.Views.Browser.LoadedFolderContents." />

  <security:protectClass 
    name="Zope.App.OFS.Folder.Views.Browser.LoadedFolderContents."
    permission_id="Zope.View" 
    methods="index, listContentInfo, remove, removeObjects, confirmRemoved, 
    moveObjectsUp, moveObjectsDown, moveObjectsToTop, moveObjectsToBottom" />

  <browser:view name="limit"
    for="Zope.App.OFS.IContainerLimit."
    factory="Zope.App.OFS.Folder.Views.Browser.FolderLimitEdit." />

  <security:protectClass 
    name="Zope.App.OFS.Folder.Views.Browser.FolderLimitEdit."
    permission_id="Zope.ManageContent" 
    methods="index, action, getFieldViews" />

  <browser:view name="LimitFieldView"
    for="Zope.App.OFS.IContainerLimit."
    factory="Zope.App.OFS.Folder.LoadedFolderFields.LimitField. Zope.App.Formulator.Widgets.Browser.TextWidget." />

  <browser:view name="adder"
    for="Zope.App.OFS.Folder.LoadedFolder.ILoadedFolder."
    factory="Zope.App.OFS.Folder.Views.Browser.FolderAdder." />

  <security:protectClass 
    name="Zope.App.OFS.Folder.Views.Browser.FolderAdder."
    permission_id="Zope.ManageContent" 
    methods="index, confirmed, action, listAddableInfo" />

</zopeConfigure>


=== Added File Zope3/lib/python/Zope/App/OFS/Folder/Views/Browser/contents.pt ===
<html metal:use-macro="views/standard_macros/page">
<head>
<style metal:fill-slot="headers" type="text/css">
<!--
.ContentListing {
    width: 100%;
}

.ContentIcon {
    width: 20px;
}

.ContentTitle {
    text-align: left;
}
-->
</style>
</head>
<body>
<div metal:fill-slot="body">

<form action="contents;view" method="get">
  <table class="ContentListing">
  
    <caption>Folder Contents <a href="../adder;view"> Add... </a> </caption>
  
    <tbody>
  
      <tr>
	<td class="ContentIcon"><br /> </td>
	<th class="ContentTitle">Title</th>
      </tr>
  
      <!--
	** listContentInfo returns a sequence of mappings, containing:
	**   'id'    : the ID of the contained within the container
	**   'url'   : the absolute URL of the contained object
	**   'title' : the title of the contained object
	**   'icon'  : the absolute URL of the icon, for the contained object
		       (may be None)
	-->
      <tr tal:repeat="info container/listContentInfo">
  
	<td class="ContentSelect">
	  <input type="checkbox" name="ids:list" value="id"
		 tal:attributes="value info/id" />
	</td>
  
	<td class="ContentIcon">
	  <img alt="Folder" src="../../ZMI/www/folder_icon.gif"
	       tal:condition="info/url"
	       tal:attributes="src info/url" />
	</td>
  
	<td class="ContentTitle">
	  <a href="subfolder_id"
	     tal:attributes="href string:../${info/url}"
	     tal:content="info/title"
	  >Folder Title or ID here</a>
	</td>
      </tr>
	  
      <tr tal:condition="nothing">
  
	<td class="ContentIcon">
	  <img alt="Document" src="../../ZMI/www/document_icon.gif" />
	</td>
  
	<td class="ContentTitle">
	   <a href="document_id">Document Title or ID here</a>
	</td>
      </tr>
    </tbody>
  
  </table>
  <br />

  <input type="submit" name="removeObjects:method" value="Delete"
         i18n:attributes="value string:menu_delete_button" /> 
</form>

<p><a href="../Services;etc/" tal:condition="here/hasServiceManager">Services</a>
<a href="addServiceManager" tal:condition="not: here/hasServiceManager">Allow Services</a>
</p>
</div>
</body>
</html>


=== Added File Zope3/lib/python/Zope/App/OFS/Folder/Views/Browser/limit.pt ===
<html metal:use-macro="views/standard_macros/page">
  <head>
    <style metal:fill-slot="headers" type="text/css">
      <!--
      .ContentIcon {
	  width: 20px;
      }
      
      .ContentTitle {
	  text-align: left;
      }
      -->
    </style>
  </head>

  <body>
    <div metal:fill-slot="body">

 
      <p tal:content="here/msg"
         tal:condition="python: hasattr(here, 'msg')">
        Message will go here.
      </p>

      <p tal:content="container/description">
        Description of the Form.
      </p>


      <div tal:condition="python: options.has_key('errors') and options['errors']">
        Errors:
        <div tal:repeat="error options/errors | nothing"
             tal:content="error">Foo </div>
      </div>

      <form action="action" method="post">

        <table class="EditTable">      
	  <tbody>   
  
	    <tr tal:repeat="fieldView python:container.getFieldViews(request)">
	      <th class="EditAttributeName"
                  tal:content="python: fieldView.getContext().getValue('title')">Title</th>
	      <td class="EditAttributeValue"
	          tal:content="structure fieldView/render"><input />
              </td>
	    </tr>
  
	  </tbody>     
      </table>

      <input type="submit" name="edit" value="Save Changes">

      </form> 

    </div>
  </body>
</html>


=== Added File Zope3/lib/python/Zope/App/OFS/Folder/Views/Browser/loaded_folder_contents.pt ===
<html metal:use-macro="views/standard_macros/page">
<head>
<style metal:fill-slot="headers" type="text/css">
<!--
.ContentListing {
    width: 100%;
}

.ContentIcon {
    width: 20px;
}

.ContentTitle {
    text-align: left;
}
-->
</style>
</head>
<body>
<div metal:fill-slot="body">

<form action="../contents;view" method="post">
  <table class="ContentListing">
  
    <caption>Folder Contents <a href="../adder;view"> Add... </a> </caption>
  
    <tbody>
  
      <tr>
	<td class="ContentIcon"><br /> </td>
	<th class="ContentTitle">Title</th>
        <th class="ContentTitle">Order</th>
      </tr>
  
      <!--
	** listContentInfo returns a sequence of mappings, containing:
	**   'id'    : the ID of the contained within the container
	**   'url'   : the absolute URL of the contained object
	**   'title' : the title of the contained object
	**   'icon'  : the absolute URL of the icon, for the contained object
		       (may be None)
	-->
      <tr tal:repeat="info container/listContentInfo">
  
	<td class="ContentSelect">
	  <input type="checkbox" name="ids:list" value="id"
		 tal:attributes="value info/id" />
	</td>
  
	<td class="ContentIcon">
	  <img alt="Folder" src="../../ZMI/www/folder_icon.gif"
	       tal:condition="info/url"
	       tal:attributes="src info/url" />
	</td>
  
	<td class="ContentTitle">
	  <a href="subfolder_id"
	     tal:attributes="href string:../${info/url}"
	     tal:content="info/title"
	  >Folder Title or ID here</a>
	</td>
        <td>
          <a href="" tal:attributes="href string:moveObjectsUp?ids=${info/id}">
            up</a>&nbsp;|
          <a href="" tal:attributes="href string:moveObjectsDown?ids=${info/id}">
            down</a>&nbsp;|
          <a href="" tal:attributes="href string:moveObjectsToTop?ids=${info/id}">
            top</a>&nbsp;|
          <a href="" tal:attributes="href string:moveObjectsToBottom?ids=${info/id}">
            bottom</a>&nbsp;|
        </td>
      </tr>
	  
      <tr tal:condition="nothing">
  
	<td class="ContentIcon">
	  <img alt="Document" src="../../ZMI/www/document_icon.gif" />
	</td>
  
	<td class="ContentTitle">
	   <a href="document_id">Document Title or ID here</a>
	</td>
      </tr>
    </tbody>
  
  </table>
  <br />

  <input type="submit" name="removeObjects:method" value="Delete"
         i18n:attributes="value string:menu_delete_button">&nbsp;
  <input type="submit" name="moveObjectsUp:method" value="Move Up" />&nbsp;
  <input type="submit" name="moveObjectsDown:method" value="Move Down" />&nbsp;
  <input type="submit" name="moveObjectsToTop:method" value="Move To Top" />&nbsp;
  <input type="submit" name="moveObjectsToBottom:method" value="Move To Bottom" />
</form>

</div>
</body>
</html>


=== Added File Zope3/lib/python/Zope/App/OFS/Folder/Views/Browser/remove_confirmed.pt ===
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<!--
      metal:use-macro="presentation/standard_macros/html">
  -->
<body>

<p> Object(s) removed successfully. </p>

</body>
</html>