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