Package logilab :: Package common :: Module html
[frames] | no frames]

Source Code for Module logilab.common.html

  1  # copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved. 
  2  # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr 
  3  # 
  4  # This file is part of logilab-common. 
  5  # 
  6  # logilab-common is free software: you can redistribute it and/or modify it under 
  7  # the terms of the GNU Lesser General Public License as published by the Free 
  8  # Software Foundation, either version 2.1 of the License, or (at your option) any 
  9  # later version. 
 10  # 
 11  # logilab-common is distributed in the hope that it will be useful, but WITHOUT 
 12  # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
 13  # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more 
 14  # details. 
 15  # 
 16  # You should have received a copy of the GNU Lesser General Public License along 
 17  # with logilab-common.  If not, see <http://www.gnu.org/licenses/>. 
 18  """render a tree in HTML. 
 19   
 20   
 21   
 22   
 23  """ 
 24  __docformat__ = "restructuredtext en" 
 25   
 26   
27 -def render_HTML_tree(tree, selected_node=None, render_node=None, caption=None):
28 """ 29 Generate a pure HTML representation of a tree given as an instance 30 of a logilab.common.tree.Node 31 32 selected_node is the currently selected node (if any) which will 33 have its surrounding <div> have id="selected" (which default 34 to a bold border libe with the default CSS). 35 36 render_node is a function that should take a Node content (Node.id) 37 as parameter and should return a string (what will be displayed 38 in the cell). 39 40 Warning: proper rendering of the generated html code depends on html_tree.css 41 """ 42 tree_depth = tree.depth_down() 43 if render_node is None: 44 render_node = str 45 46 # helper function that build a matrix from the tree, like: 47 # +------+-----------+-----------+ 48 # | root | child_1_1 | child_2_1 | 49 # | root | child_1_1 | child_2_2 | 50 # | root | child_1_2 | | 51 # | root | child_1_3 | child_2_3 | 52 # | root | child_1_3 | child_2_4 | 53 # +------+-----------+-----------+ 54 # from: 55 # root -+- child_1_1 -+- child_2_1 56 # | | 57 # | +- child_2_2 58 # +- child_1_2 59 # | 60 # +- child1_3 -+- child_2_3 61 # | 62 # +- child_2_2 63 def build_matrix(path, matrix): 64 if path[-1].is_leaf(): 65 matrix.append(path[:]) 66 else: 67 for child in path[-1].children: 68 build_matrix(path[:] + [child], matrix)
69 70 matrix = [] 71 build_matrix([tree], matrix) 72 73 # make all lines in the matrix have the same number of columns 74 for line in matrix: 75 line.extend([None]*(tree_depth-len(line))) 76 for i in range(len(matrix)-1, 0, -1): 77 prev_line, line = matrix[i-1:i+1] 78 for j in range(len(line)): 79 if line[j] == prev_line[j]: 80 line[j] = None 81 82 # We build the matrix of link types (between 2 cells on a line of the matrix) 83 # link types are : 84 link_types = {(True, True, True ): 1, # T 85 (False, False, True ): 2, # | 86 (False, True, True ): 3, # + (actually, vert. bar with horiz. bar on the right) 87 (False, True, False): 4, # L 88 (True, True, False): 5, # - 89 } 90 links = [] 91 for i, line in enumerate(matrix): 92 links.append([]) 93 for j in range(tree_depth-1): 94 cell_11 = line[j] is not None 95 cell_12 = line[j+1] is not None 96 cell_21 = line[j+1] is not None and line[j+1].next_sibling() is not None 97 link_type = link_types.get((cell_11, cell_12, cell_21), 0) 98 if link_type == 0 and i > 0 and links[i-1][j] in (1, 2, 3): 99 link_type = 2 100 links[-1].append(link_type) 101 102 103 # We can now generate the HTML code for the <table> 104 s = u'<table class="tree">\n' 105 if caption: 106 s += '<caption>%s</caption>\n' % caption 107 108 for i, link_line in enumerate(links): 109 line = matrix[i] 110 111 s += '<tr>' 112 for j, link_cell in enumerate(link_line): 113 cell = line[j] 114 if cell: 115 if cell.id == selected_node: 116 s += '<td class="tree_cell" rowspan="2"><div class="selected tree_cell">%s</div></td>' % (render_node(cell.id)) 117 else: 118 s += '<td class="tree_cell" rowspan="2"><div class="tree_cell">%s</div></td>' % (render_node(cell.id)) 119 else: 120 s += '<td rowspan="2">&nbsp;</td>' 121 s += '<td class="tree_cell_%d_1">&nbsp;</td>' % link_cell 122 s += '<td class="tree_cell_%d_2">&nbsp;</td>' % link_cell 123 124 cell = line[-1] 125 if cell: 126 if cell.id == selected_node: 127 s += '<td class="tree_cell" rowspan="2"><div class="selected tree_cell">%s</div></td>' % (render_node(cell.id)) 128 else: 129 s += '<td class="tree_cell" rowspan="2"><div class="tree_cell">%s</div></td>' % (render_node(cell.id)) 130 else: 131 s += '<td rowspan="2">&nbsp;</td>' 132 133 s += '</tr>\n' 134 if link_line: 135 s += '<tr>' 136 for j, link_cell in enumerate(link_line): 137 s += '<td class="tree_cell_%d_3">&nbsp;</td>' % link_cell 138 s += '<td class="tree_cell_%d_4">&nbsp;</td>' % link_cell 139 s += '</tr>\n' 140 141 s += '</table>' 142 return s 143