From 23bb0fd8cbd2f46db02d07d5503a3c788a6c9d3d Mon Sep 17 00:00:00 2001
From: Yoshinori Okuji <yo@nexedi.com>
Date: Fri, 23 Jun 2006 05:07:09 +0000
Subject: [PATCH] Heavy rewrite with Page Template.

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@8147 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ERP5Form/ListBox.py             |  82 +++++-
 product/ERP5Form/www/ListBox_asHTML.zpt | 323 ++++++++++++++++++++++++
 2 files changed, 400 insertions(+), 5 deletions(-)
 create mode 100644 product/ERP5Form/www/ListBox_asHTML.zpt

diff --git a/product/ERP5Form/ListBox.py b/product/ERP5Form/ListBox.py
index 5dbc549ee7..ae1257be0d 100644
--- a/product/ERP5Form/ListBox.py
+++ b/product/ERP5Form/ListBox.py
@@ -50,6 +50,7 @@ from ZODB.POSException import ConflictError
 
 from Globals import InitializeClass, Persistent, Acquisition, get_request
 from Products.PythonScripts.Utility import allow_class
+from Products.PageTemplates.PageTemplateFile import PageTemplateFile
 
 import random
 import md5
@@ -102,6 +103,8 @@ class ReportTree:
     else:
       self.domain_url = relative_url
 
+allow_class(ReportTree)
+
 class ReportSection:
   """This class describes a report section.
   """
@@ -335,11 +338,19 @@ class ListBoxWidget(Widget.Widget):
     list_action = fields.StringField('list_action',
                                  title='List Action',
                                  description=('The id of the object action'
-                                              'to display the current list'),
+                                              ' to display the current list'),
                                  default='list',
                                  required=1)
     property_names.append('list_action')
 
+    page_template = fields.StringField('page_template',
+                                 title='Page Template',
+                                 description=('The id of a Page Template'
+                                              ' to render the ListBox'),
+                                 default='',
+                                 required=0)
+    property_names.append('page_template')
+
     def render_view(self, field, value, REQUEST=None, render_format='html', key='listbox'):
         """
           Render a ListBox in read-only.
@@ -858,6 +869,13 @@ class ListBoxRenderer:
 
   getCheckedUidList = VolatileCachingMethod(getCheckedUidList)
 
+  def getCheckedUidSet(self):
+    """Return the set of checked uids.
+    """
+    return set(self.getCheckedUidList())
+
+  getCheckedUidSet = VolatileCachingMethod(getCheckedUidSet)
+
   def getSelectedColumnList(self):
     """Return the list of selected columns.
     """
@@ -1916,7 +1934,7 @@ class ListBoxHTMLRendererLine(ListBoxRendererLine):
                   error = sys.exc_info())
           else:
             try:
-              url = '%s/view?selection_index=%s&selection_name=%s&reset:int=1' % (brain.getPath(), self.index, selection_name)
+              url = '%s/view?selection_index=%s&amp;selection_name=%s&amp;reset:int=1' % (brain.getPath(), self.index, selection_name)
             except AttributeError:
               pass
 
@@ -1930,6 +1948,19 @@ class ListBoxHTMLRendererLine(ListBoxRendererLine):
 
     return html_list
 
+allow_class(ListBoxHTMLRendererLine)
+
+class ListBoxRendererContext(Acquisition.Explicit):
+  """This class helps making a context for a Page Template,
+  because Page Template requires an acquisition context.
+  """
+  def __init__(self, renderer):
+    self.renderer = renderer
+    # XXX this is a workaround for GlobalTranslationService.
+    self.Localizer = renderer.getContext().Localizer
+
+  def __getattr__(self, name):
+    return getattr(self.renderer, name)
 
 class ListBoxHTMLRenderer(ListBoxRenderer):
   """This class implements HTML rendering for ListBox.
@@ -1983,6 +2014,27 @@ class ListBoxHTMLRenderer(ListBoxRenderer):
 
     return md5_string
 
+  def getPhysicalRoot(self):
+    """Return the physical root (an Application object). This method is required for
+    Page Template to make a context.
+    """
+    return self.getContext().getPhysicalRoot()
+
+  asHTML = PageTemplateFile('www/ListBox_asHTML', globals())
+
+  def getPageTemplate(self):
+    """Return a Page Template to render.
+    """
+    context = ListBoxRendererContext(self)
+
+    # If a specific template is specified, use it.
+    method_id = self.field.get_value('page_template')
+    if method_id:
+      return getattr(context, method_id)
+
+    # Otherwise, use the default one.
+    return context.asHTML
+
   def render(self, **kw):
     """Render the data in HTML.
     """
@@ -1998,6 +2050,24 @@ class ListBoxHTMLRenderer(ListBoxRenderer):
       selection.edit(method_path = method_path, list_url = list_url)
       self.getSelectionTool().setSelectionFor(self.getSelectionName(), selection, REQUEST = self.request)
 
+    pt = self.getPageTemplate()
+    return pt()
+
+  def original_render(self, **kw):
+    """This is just a reference. Not used any longer.
+    """
+    # Make it sure to store the current selection, only if a list method is defined.
+    list_method = self.getListMethod()
+    selection = self.getSelection()
+    if list_method is not None:
+      method_path = getPath(self.getContext()) + '/' + self.getListMethodName()
+      list_url = '%s?selection_name=%s' % (self.getUrl(), self.getRequestedSelectionName())
+      selection_index = self.getSelectionIndex()
+      if selection_index is not None:
+        list_url += '&selection_index=%s' % selection_index
+      selection.edit(method_path = method_path, list_url = list_url)
+      self.getSelectionTool().setSelectionFor(self.getSelectionName(), selection, REQUEST = self.request)
+
     # Obtain the list of lines.
     line_list = self.query()
 
@@ -2335,7 +2405,7 @@ class ListBoxHTMLRenderer(ListBoxRenderer):
 
           if alias is not None:
             # Render the search field by a widget, if any.
-            if search_field:
+            if search_field is not None:
               search_field_html = search_field.render(value = param, key = alias)
             else:
               search_field_html = """<input name="%s" size="8" value="%s" />""" % (alias, cgi.escape(param))
@@ -2356,7 +2426,7 @@ class ListBoxHTMLRenderer(ListBoxRenderer):
 
     # Add data lines.
     selection = self.getSelection()
-    checked_uid_set = set(self.getCheckedUidList())
+    checked_uid_set = self.getCheckedUidSet()
 
     for i, line in enumerate(line_list):
       # Change the appearance of each line for visibility.
@@ -2503,6 +2573,8 @@ class ListBoxHTMLRenderer(ListBoxRenderer):
 
     return ''.join(html_list)
 
+allow_class(ListBoxHTMLRenderer)
+
 class ListBoxListRenderer(ListBoxRenderer):
   """This class implements list rendering for ListBox.
   """
@@ -3047,7 +3119,7 @@ allow_class(ListBoxLine)
 
 # Psyco
 import psyco
-psyco.bind(ListBoxWidget.render)
+#psyco.bind(ListBoxWidget.render)
 psyco.bind(ListBoxValidator.validate)
 
 
diff --git a/product/ERP5Form/www/ListBox_asHTML.zpt b/product/ERP5Form/www/ListBox_asHTML.zpt
new file mode 100644
index 0000000000..cab22fe9fe
--- /dev/null
+++ b/product/ERP5Form/www/ListBox_asHTML.zpt
@@ -0,0 +1,323 @@
+<tal:block
+  xmlns:tal="http://xml.zope.org/namespaces/tal"
+  xmlns:metal="http://xml.zope.org/namespaces/metal"
+  xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+  tal:define="field_id here/getId;
+              form_id python: here.getForm().id;
+              selection_name here/getSelectionName;
+              requested_selection_name here/getRequestedSelectionName;
+              selection_index here/getSelectionIndex;
+              selection here/getSelection;
+              portal_url_string here/getPortalUrlString;
+              real_context here/getContext;
+              context_url real_context/getUrl;
+              md5_string here/getMD5Checksum;
+              line_list here/query;
+              is_domain_tree_mode here/isDomainTreeMode;
+              is_report_tree_mode here/isReportTreeMode;
+              is_domain_tree_supported here/isDomainTreeSupported;
+              is_report_tree_supported here/isReportTreeSupported;
+              show_select_column here/showSelectColumn;
+              show_search_line here/showSearchLine;
+              ">
+  <!-- ListBox starts here.  -->
+  <input type="hidden" name="list_selection_name" value="default" tal:attributes="value selection_name" />
+  <input tal:condition="md5_string" type="hidden" name="md5_object_uid_list" value="checksum" tal:attributes="value md5_string" />
+
+  <tal:replace tal:content="nothing">
+    Because TAL cannot accept unbalanced tags, the support for a domain tree is realized by a macro.
+    The macro ListBoxContainer is a no-op, if not in domain tree mode. Otherwise, the macro constructs
+    a domain tree and extracts the body in an extra table.
+  </tal:replace>
+
+  <tal:block tal:define="expand python: 0">
+    <tal:block metal:define-macro="ListBoxContainer">
+      <tal:block tal:condition="expand">
+        <table tal:condition="is_domain_tree_mode"
+          border="0" cellpadding="0" cellspacing="0" width="100%"
+          tal:define="selected_domain_path here/getSelectedDomainPath">
+          <tr>
+            <td valign="top">
+              <select name="domain_root_url" onChange="submitAction(this.form, 'context/portal_selections/setDomainRoot')"
+                tal:attributes="onChange string:submitAction(this.form, '${context_url}/portal_selections/setDomainRoot')"
+                tal:repeat="c here/getDomainRootList">
+                <option value="base_domain"
+                  tal:define="path python: c[0]; title python: c[1]"
+                  tal:attributes="selected python: path == selected_domain_path; value path"
+                  tal:content="title"
+                  i18n:translate="" i18n:domain="ui">Base Domain</option>
+              </select>
+              <table id="listbox_domain_tree_table" cellpadding="0" border="0"
+                tal:attributes="id string:${field_id}_domain_tree_table"
+                tal:define="report_tree_list python: here.makeReportTreeList(report_path = selected_domain_path, unfolded_list = selection.getDomainList(), is_report_opened = False);
+                            total_depth python: max([report_tree.depth for report_tree in report_tree_list] + [-1])">
+                <tr tal:repeat="report_tree report_tree_list">
+                  <tal:block tal:repeat="i python: range(report_tree.depth)">
+                    <td width="16" nowrap="nowrap">&nbsp;</td>
+                  </tal:block>
+                  <td nowrap="nowrap" valign="top" align="left" colspan="1"
+                    tal:attributes="colspan python: total_depth - report_tree.depth + 1">
+                    <a href="method"
+                      tal:condition="report_tree/is_open"
+                      tal:attributes="href string:portal_selections/foldDomain?domain_url=${report_tree/domain_url}&form_id=${form_id}&list_selection_name=${selection_name}&domain_depth:int=${report_tree/depth}">-&nbsp;<b tal:content="report_tree/obj/getTitleOrId" i18n:translate="" i18n:domain="ui">Domain</b></a>
+                    <a href="method"
+                      tal:condition="not: report_tree/is_open"
+                      tal:attributes="href string:portal_selections/unfoldDomain?domain_url=${report_tree/domain_url}&form_id=${form_id}&list_selection_name=${selection_name}&domain_depth:int=${report_tree/depth}">+&nbsp;<tal:block tal:content="report_tree/obj/getTitleOrId" i18n:translate="" i18n:domain="ui">Domain</tal:block></a>
+                  </td>
+                </tr>
+              </table>
+            </td>
+            <td valign="top">
+              <tal:block metal:define-slot="ListBoxBody" />
+            </td>
+          </tr>
+        </table>
+        <tal:block tal:condition="not: is_domain_tree_mode">
+          <tal:block metal:define-slot="ListBoxBody" />
+        </tal:block>
+      </tal:block>
+    </tal:block>
+  </tal:block>
+
+  <tal:block tal:define="expand python: 1">
+    <tal:block metal:use-macro="template/macros/ListBoxContainer">
+      <tal:block metal:fill-slot="ListBoxBody">
+        <div class="ListSummary">
+          <table border="0" cellpadding="0" cellspacing="0">
+            <tr>
+              <td height="10">
+                <img src="Left.png" alt="left"
+                  tal:attributes="src string:${portal_url_string}/images/Left.png" />
+              </td>
+              <td class="Top" colspan="2" height="10">
+                <img src="spacer.png" width="5" height="10" alt="spacer"
+                  tal:attributes="src string:${portal_url_string}/images/spacer.png" />
+              </td>
+              <td class="Top" colspan="3" height="10">
+                <img src="spacer.png" width="5" height="10" alt="spacer"
+                  tal:attributes="src string:${portal_url_string}/images/spacer.png" />
+              </td>
+            </tr>
+            <tr id="listbox_title_line" tal:attributes="id string:${field_id}_title_line">
+              <td class="Left" width="17">
+                <img src="spacer.png" width="5" height="5" alt="spacer"
+                  tal:attributes="src string:${portal_url_string}/images/spacer.png" />
+              </td>
+              <td valign="middle" nowrap="nowrap">
+                <input tal:condition="python: is_domain_tree_supported or is_report_tree_supported"
+                  type="image" src="text_block.png" id="listbox_flat_list_mode"
+                  title="Flat List" name="portal_selections/setFlatListMode:method"
+                  value="1" alt="Flat List"
+                  tal:attributes="src string:${portal_url_string}/images/text_block.png;
+                                  id string:${field_id}_flat_list_mode"
+                  i18n:domain="ui" i18n:attributes="title" />
+                <input tal:condition="is_report_tree_supported"
+                  type="image" src="view_tree.png" id="listbox_report_tree_mode"
+                  title="Report Tree" name="portal_selections/setReportTreeMode:method"
+                  value="1" alt="Report Tree"
+                  tal:attributes="src string:${portal_url_string}/images/view_tree.png;
+                                  id string:${field_id}_report_tree_mode"
+                  i18n:domain="ui" i18n:attributes="title" />
+                <input tal:condition="is_domain_tree_supported"
+                  type="image" src="view_choose.png" id="listbox_domain_tree_mode"
+                  title="Domain Tree" name="portal_selections/setDomainTreeMode:method"
+                  value="1" alt="Domain Tree"
+                  tal:attributes="src string:${portal_url_string}/images/view_choose.png;
+                                  id string:${field_id}_domain_tree_mode"
+                  i18n:domain="ui" i18n:attributes="title" />
+              </td>
+              <td width="100%" valign="middle">
+                &nbsp;
+                <a id="listbox_title" href="list"
+                  tal:attributes="id string:${field_id}_title; href here/getListActionUrl"
+                  tal:content="here/getTitle" i18n:domain="ui" i18n:translate="">Title</a>:
+                <span id="listbox_record_number"
+                  tal:attributes="id string:${field_id}_record_number"
+                  i18n:translate="" i18n:domain="ui"><tal:block tal:replace="here/total_size" i18n:name="number">0</tal:block> record(s)</span>
+                - <span id="listbox_item_number"
+                    tal:attributes="id string:${field_id}_item_number"
+                    i18n:translate="" i18n:domain="ui"><tal:block tal:replace="python: len(here.getCheckedUidList())" i18n:name="number">0</tal:block> item(s) selected</span>
+              </td>
+              <td nowrap="nowrap" valign="middle" align="center">
+                <input tal:condition="python: here.current_page > 0"
+                  id="listbox_previous_page" type="image" src="1leftarrowv.png"
+                  title="Previous Page" name="portal_selections/previousPage:method" border="0"
+                  tal:attributes="id string:${field_id}_previous_page;
+                                  src string:${portal_url_string}/images/1leftarrowv.png"
+                  i18n:domain="ui" i18n:attributes="title" />
+              </td>
+              <td nowrap="nowrap" valign="middle" align="center">
+                <select id="listbox_page_selection" name="list_start" title="Change Page" size="1"
+                  onChange="submitAction(this.form, 'context/portal_selections/setPage')"
+                  tal:define="lines here/getMaxLineNumber"
+                  tal:attributes="id string:${field_id}_page_selection;
+                                  onChange string:submitAction(this.form, '${context_url}/portal_selections/setPage')"
+                  i18n:domain="ui" i18n:attributes="title">
+                  <option value="0"
+                    tal:repeat="p python: range(0, here.total_pages)"
+                    tal:attributes="selected python: p == here.current_page;
+                                    value python: p * lines"
+                    i18n:domain="ui" i18n:translate=""><tal:block tal:replace="python: p + 1" i18n:name="page">0</tal:block> of <tal:block tal:replace="here/total_pages" i18n:name="total_pages">1</tal:block></option>
+                </select>
+              </td>
+              <td nowrap="nowrap" valign="middle" align="center">
+                <input tal:condition="python: here.current_page < here.total_pages - 1"
+                  id="listbox_next_page" type="image" src="1rightarrowv.png"
+                  title="Next Page" name="portal_selections/nextPage:method" border="0"
+                  tal:attributes="id string:${field_id}_next_page;
+                                  src string:${portal_url_string}/images/1rightarrowv.png"
+                  i18n:domain="ui" i18n:attributes="title" />
+              </td>
+            </tr>
+          </table>
+        </div>
+        <div class="ListContent">
+          <table cellpadding="0" cellspacing="0" border="0">
+            <tr id="listbox_label_line" tal:attributes="id string:${field_id}_label_line">
+              <td tal:condition="is_report_tree_mode"
+                class="Data" width="50" align="left" valign="middle">
+                <select name="report_root_url"
+                  onChange="submitAction(this.form, 'context/portal_selections/setReportRoot')"
+                  tal:attributes="onChange string:submitAction(this.form, '${context_url}/portal_selections/setReportRoot')">
+                  <tal:block tal:repeat="c here/getReportRootList">
+                    <option value="base_domain"
+                      tal:define="path python: c[0]; title python: c[1]"
+                      tal:attributes="selected python: path == here.getSelectedReportPath(); value path"
+                      tal:content="title" i18n:domain="ui" i18n:translate="">Domain</option>
+                  </tal:block>
+                </select>
+              </td>
+              <td tal:condition="show_select_column"
+                class="Data" width="50" align="center" valign="middle">
+                <input id="listbox_check_all" type="image"
+                  name="portal_selections/checkAll:method" value="1"
+                  src="checkall.png" border="0" alt="Check All" title="Check All"
+                  tal:attributes="id string:${field_id}_check_all;
+                                  src string:${portal_url_string}/images/checkall.png"
+                  i18n:domain="ui" i18n:attributes="title" />&nbsp;<input id="listbox_uncheck_all" type="image" name="portal_selections/uncheckAll:method" value="1"
+                  src="%(portal_url_string)s/images/decheckall.png" border="0" alt="Uncheck All" title="Uncheck All"
+                  tal:attributes="id string:${field_id}_uncheck_all;
+                                  src string:${portal_url_string}/images/decheckall.png"
+                  i18n:domain="ui" i18n:attributes="title" />
+              </td>
+              <tal:block tal:repeat="value here/getLabelValueList">
+                <tal:block tal:define="sql python: value[0];
+                                       title python: value[1];
+                                       sort_order python: value[2]">
+                  <td tal:condition="sql" class="Data">
+                    <a href="portal_selections/setSelectionQuickSortOrder?selection_name=default&amp;sort_on=id"
+                      tal:attributes="href string:portal_selections/setSelectionQuickSortOrder?selection_name=${selection_name}&amp;sort_on=${sql}"
+                      tal:content="title" i18n:domain="ui" i18n:translate="">ID</a>
+                    <img tal:condition="python: sort_order == 'ascending'"
+                      src="1bottomarrow.png" alt="Ascending Display" title="Ascending Display"
+                      tal:attributes="src string:${portal_url_string}/images/1bottomarrow.png"
+                      i18n:domain="ui" i18n:attributes="title" />
+                    <img tal:condition="python: sort_order == 'descending'"
+                      src="1toparrow.png" alt="Descending Display" title="Descending Display"
+                      tal:attributes="src string:${portal_url_string}/images/1toparrow.png"
+                      i18n:domain="ui" i18n:attributes="title" />
+                  </td>
+                  <td tal:condition="not: sql" class="Data" tal:content="title"
+                    i18n:domain="ui" i18n:translate="">
+                    ID
+                  </td>
+                </tal:block>
+              </tal:block>
+            </tr>
+
+            <tr tal:condition="python: show_search_line or is_report_tree_mode"
+              id="listbox_search_line"
+              tal:attributes="id python: show_search_line and ('%s_search_line' % field_id) or ('%s_report_depth_line' % field_id)">
+              <tal:block tal:condition="is_report_tree_mode">
+                <td class="Data" width="50" align="left" valign="middle" colspan="1"
+                  tal:attributes="colspan python: show_search_line and 1 or (len(here.getSelectedColumnList()) + show_select_column + 1)"
+                  tal:define="index python: selection_index is not None and '&amp;selection_index=%d' % selection_index or '';
+                              is_report_opened python: not here.getSelection().isReportOpened();
+                              url here/getUrl"><tal:block tal:repeat="i python: range(0, 6)">&nbsp;<a href="?selection_name=default&amp;selection_index=0&amp;report_depth:int=0"
+                            tal:attributes="href string:${url}?selection_name=${requested_selection_name}${index}&amp;report_depth:int=${i}"
+                            tal:content="i">0</a></tal:block>&nbsp;-&nbsp;<a href="?selection_name=default&amp;selection_index=0&amp;is_report_opened:int=0"
+                                tal:attributes="href string:${url}?selection_name=${requested_selection_name}${index}&amp;is_report_opened:int=${is_report_opened}"
+                                tal:content="python: is_report_opened and 'Show' or 'Hide'"
+                                i18n:domain="ui" i18n:translate="">Show</a>
+                </td>
+              </tal:block>
+              <td tal:condition="python: show_select_column and show_search_line"
+                class="Data" width="50" align="center" valign="middle">
+                <input id="listbox_select" type="image" src="exec16.png"
+                  title="Action" alt="Action" name="Base_doSelect:method"
+                  tal:attributes="id string:${field_id}_select;
+                                  src string:${portal_url_string}/images/exec16.png"
+                  i18n:domain="ui" i18n:attributes="title" />
+              </td>
+              <tal:block tal:condition="show_search_line"
+                tal:repeat="value here/getSearchValueList">
+                <td class="DataB"
+                  tal:define="alias python: value[0];
+                              param python: value[1];
+                              search_field python: value[2]">
+                  <font tal:condition="alias" size="-3">
+                    <tal:block tal:condition="python: search_field is not None"
+                      tal:replace="structure python: search_field.render(value = param, key = alias)" />
+                    <input tal:condition="python: search_field is None" name="id" size="8" value=""
+                      tal:attributes="name alias; value param" />
+                  </font>
+                </td>
+              </tal:block>
+            </tr>
+
+            <tal:block tal:repeat="line line_list" tal:define="checked_uid_set here/getCheckedUidSet">
+              <tr id="listbox_data_line_0" class="DataA"
+                tal:define="css python: test(repeat['line'].index % 2, 'DataB', 'DataA')"
+                tal:attributes="id string:${field_id}_data_line_${repeat/line/index}; class css">
+                <td tal:condition="is_report_tree_mode" class="DataA" align="left" valign="middle"
+                  tal:attributes="class css"
+                  tal:define="section_name python: line.getContext() is not None and line.getContext().getTitleOrId() or ''">
+                  <input type="hidden" value="1" name="listbox_uid:list"
+                    tal:attributes="value python: line.getUid() or ''; name string:${field_id}_uid:list" />
+                  <a tal:condition="section_name"
+                    href="portal_selections/foldReport?report_url=base_domain&amp;form_id=form&amp;list_selection_name=default"
+                    tal:define="method_id python: line.isOpen() and 'foldReport' or 'unfoldReport'"
+                    tal:attributes="href string:portal_selections/${method_id}?report_url=${line/getDomainUrl}&amp;form_id=${form_id}&amp;list_selection_name=${selection_name}"
+                    tal:content="structure python: '%s%s&nbsp;%s' % ('&nbsp;&nbsp;' * line.getDepth(), line.isOpen() and '-' or '+', section_name)" />
+                </td>
+                <td tal:condition="here/showSelectColumn"
+                  class="DataA" width="50" align="center" valign="middle"
+                  tal:attributes="class css">
+                  <input tal:condition="python: not line.isSummary() and line.getObject() is not None"
+                    type="checkbox" value="checked" id="listbox_cb_1" name="uids:list"
+                    tal:attributes="checked python: line.getUid() in checked_uid_set;
+                                    value line/getUid;
+                                    id string:${field_id}_cb_${line/getUid}" />
+                  <tal:block tal:condition="python: line.isSummary() or line.getObject() is None"></tal:block>
+                </td>
+                <tal:block tal:repeat="value line/render">
+                  <td tal:define="html python: value[0];
+                                  original_value python: value[1];
+                                  error python: value[2]"
+                    class="DataA" align="left"
+                    tal:attributes="class python: error and (css + 'Error') or css;
+                                    align python: isinstance(original_value, (float, int, long)) and 'right' or 'left'"
+                    tal:content="structure html" />
+                </tal:block>
+              </tr>
+            </tal:block>
+
+            <tr tal:condition="here/showStat" id="listbox_stat_line"
+              tal:attributes="id string:${field_id}_stat_line">
+              <td tal:condition="is_report_tree_mode" class="Data">&nsbp;</td>
+              <td tal:condition="show_select_column" class="Data">&nsbp;</td>
+              <tal:block tal:repeat="value here/getStatValueList">
+                <td class="Data" align="left"
+                  tal:define="original_value python: value[0]; processed_value python: value[1]"
+                  tal:attributes="align python: isinstance(original_value, (float, int, long)) and 'right' or 'left'"
+                  tal:content="processed_value" />
+              </tal:block>
+            </tr>
+          </table>
+        </div>
+      </tal:block>
+    </tal:block>
+  </tal:block>
+  <!-- ListBox ends here.  -->
+
+</tal:block>
-- 
2.30.9