common/uilib.py
branch3.5
changeset 2933 d511ddcd2689
parent 2516 b58826130680
child 2968 0e3460341023
child 3002 a9d7eaa07475
equal deleted inserted replaced
2932:90ad3f31204a 2933:d511ddcd2689
    10 """
    10 """
    11 __docformat__ = "restructuredtext en"
    11 __docformat__ = "restructuredtext en"
    12 
    12 
    13 import csv
    13 import csv
    14 import re
    14 import re
    15 from urllib import quote as urlquote
       
    16 from StringIO import StringIO
    15 from StringIO import StringIO
    17 
    16 
    18 from logilab.mtconverter import xml_escape, html_unescape
    17 from logilab.mtconverter import xml_escape, html_unescape
    19 
    18 
    20 from cubicweb.utils import ustrftime
    19 from cubicweb.utils import ustrftime
   261     formater.format(layout, stream)
   260     formater.format(layout, stream)
   262     res = stream.getvalue()
   261     res = stream.getvalue()
   263     if isinstance(res, str):
   262     if isinstance(res, str):
   264         res = unicode(res, 'UTF8')
   263         res = unicode(res, 'UTF8')
   265     return res
   264     return res
   266 
       
   267 def render_HTML_tree(tree, selected_node=None, render_node=None, caption=None):
       
   268     """
       
   269     Generate a pure HTML representation of a tree given as an instance
       
   270     of a logilab.common.tree.Node
       
   271 
       
   272     selected_node is the currently selected node (if any) which will
       
   273     have its surrounding <div> have id="selected" (which default
       
   274     to a bold border libe with the default CSS).
       
   275 
       
   276     render_node is a function that should take a Node content (Node.id)
       
   277     as parameter and should return a string (what will be displayed
       
   278     in the cell).
       
   279 
       
   280     Warning: proper rendering of the generated html code depends on html_tree.css
       
   281     """
       
   282     tree_depth = tree.depth_down()
       
   283     if render_node is None:
       
   284         render_node = str
       
   285 
       
   286     # helper function that build a matrix from the tree, like:
       
   287     # +------+-----------+-----------+
       
   288     # | root | child_1_1 | child_2_1 |
       
   289     # | root | child_1_1 | child_2_2 |
       
   290     # | root | child_1_2 |           |
       
   291     # | root | child_1_3 | child_2_3 |
       
   292     # | root | child_1_3 | child_2_4 |
       
   293     # +------+-----------+-----------+
       
   294     # from:
       
   295     # root -+- child_1_1 -+- child_2_1
       
   296     #       |             |
       
   297     #       |             +- child_2_2
       
   298     #       +- child_1_2
       
   299     #       |
       
   300     #       +- child1_3 -+- child_2_3
       
   301     #                    |
       
   302     #                    +- child_2_2
       
   303     def build_matrix(path, matrix):
       
   304         if path[-1].is_leaf():
       
   305             matrix.append(path[:])
       
   306         else:
       
   307             for child in path[-1].children:
       
   308                 build_matrix(path[:] + [child], matrix)
       
   309 
       
   310     matrix = []
       
   311     build_matrix([tree], matrix)
       
   312 
       
   313     # make all lines in the matrix have the same number of columns
       
   314     for line in matrix:
       
   315         line.extend([None]*(tree_depth-len(line)))
       
   316     for i in range(len(matrix)-1, 0, -1):
       
   317         prev_line, line = matrix[i-1:i+1]
       
   318         for j in range(len(line)):
       
   319             if line[j] == prev_line[j]:
       
   320                 line[j] = None
       
   321 
       
   322     # We build the matrix of link types (between 2 cells on a line of the matrix)
       
   323     # link types are :
       
   324     link_types = {(True,  True,  True ): 1, # T
       
   325                   (False, False, True ): 2, # |
       
   326                   (False, True,  True ): 3, # + (actually, vert. bar with horiz. bar on the right)
       
   327                   (False, True,  False): 4, # L
       
   328                   (True,  True,  False): 5, # -
       
   329                   }
       
   330     links = []
       
   331     for i, line in enumerate(matrix):
       
   332         links.append([])
       
   333         for j in range(tree_depth-1):
       
   334             cell_11 = line[j] is not None
       
   335             cell_12 = line[j+1] is not None
       
   336             cell_21 = line[j+1] is not None and line[j+1].next_sibling() is not None
       
   337             link_type = link_types.get((cell_11, cell_12, cell_21), 0)
       
   338             if link_type == 0 and i > 0 and links[i-1][j] in (1, 2, 3):
       
   339                 link_type = 2
       
   340             links[-1].append(link_type)
       
   341 
       
   342 
       
   343     # We can now generate the HTML code for the <table>
       
   344     s = u'<table class="tree">\n'
       
   345     if caption:
       
   346         s += '<caption>%s</caption>\n' % caption
       
   347 
       
   348     for i, link_line in enumerate(links):
       
   349         line = matrix[i]
       
   350 
       
   351         s += '<tr>'
       
   352         for j, link_cell in enumerate(link_line):
       
   353             cell = line[j]
       
   354             if cell:
       
   355                 if cell.id == selected_node:
       
   356                     s += '<td class="tree_cell" rowspan="2"><div id="selected" class="tree_cell">%s</div></td>' % (render_node(cell.id))
       
   357                 else:
       
   358                     s += '<td class="tree_cell" rowspan="2"><div class="tree_cell">%s</div></td>' % (render_node(cell.id))
       
   359             else:
       
   360                 s += '<td rowspan="2">&nbsp;</td>'
       
   361             s += '<td class="tree_cell_%d_1">&nbsp;</td>' % link_cell
       
   362             s += '<td class="tree_cell_%d_2">&nbsp;</td>' % link_cell
       
   363 
       
   364         cell = line[-1]
       
   365         if cell:
       
   366             if cell.id == selected_node:
       
   367                 s += '<td class="tree_cell" rowspan="2"><div id="selected" class="tree_cell">%s</div></td>' % (render_node(cell.id))
       
   368             else:
       
   369                 s += '<td class="tree_cell" rowspan="2"><div class="tree_cell">%s</div></td>' % (render_node(cell.id))
       
   370         else:
       
   371             s += '<td rowspan="2">&nbsp;</td>'
       
   372 
       
   373         s += '</tr>\n'
       
   374         if link_line:
       
   375             s += '<tr>'
       
   376             for j, link_cell in enumerate(link_line):
       
   377                 s += '<td class="tree_cell_%d_3">&nbsp;</td>' % link_cell
       
   378                 s += '<td class="tree_cell_%d_4">&nbsp;</td>' % link_cell
       
   379             s += '</tr>\n'
       
   380 
       
   381     s += '</table>'
       
   382     return s
       
   383 
       
   384 
   265 
   385 
   266 
   386 # traceback formatting ########################################################
   267 # traceback formatting ########################################################
   387 
   268 
   388 import traceback
   269 import traceback