Commits

Luke Plant  committed ba91efc

Added checking for max column violations for inner columns

  • Participants
  • Parent commits a00df28

Comments (0)

Files changed (2)

File semanticeditor/tests.py

                            'newcol_h1_6':[NEWCOL],
                            })
 
+    def test_max_cols_nested_2(self):
+        """
+        Tests TooManyColumns is raised when the nested layout has too many columns
+        """
+        html = "<h1>1</h1><h1>2</h1><h1>3</h1><h1>4</h1><h1>5</h1><h1>6</h1>"
+        self.assertRaises(TooManyColumns, format_html, html,
+                          {'newrow_h1_1':[NEWROW],
+                           'newcol_h1_1':[NEWCOL],
+                           'innerrow_h1_1':[NEWINNERROW],
+                           'innercol_h1_2':[NEWINNERCOL],
+                           'innercol_h1_3':[NEWINNERCOL],
+                           'innercol_h1_4':[NEWINNERCOL],
+                           'innercol_h1_5':[NEWINNERCOL],
+                           'newcol_h1_6':[NEWCOL],
+                           })
+
 
     def test_format_pre(self):
         html = "<pre>This\r\nis\r\na\r\ntest</pre>"

File semanticeditor/utils/presentation.py

 
     # Create layout from row/column commands
     layout = _create_layout(root, styleinfo, structure)
-    _check_layout(layout, structure, layout_strategy)
+    for c in layout.content:
+        _check_layout(c, structure, layout_strategy)
     # Create new ET tree from layout.  The individual nodes that belong to
     # 'root' are not altered, but just added to a new tree.  This means that the
     # information in 'structure' does not need updating.
         self.content = []
         self.presinfo = presinfo
 
+    def column_count(self):
+        """
+        Get the number of logical columns.
+        """
+        return sum(_layout_column_width(c) for c in self.content)
+
     def as_nodes(self, layout_strategy):
         """
         Returns layout as a list of ElementTree nodes
         """
         # Row
-        logical_column_count = _layout_column_count(self)
+        logical_column_count = self.column_count()
         actual_column_count = len(self.content)
         rowdiv = ET.Element('div')
         classes = layout_strategy.row_classes(logical_column_count, actual_column_count) + _get_classes_from_presinfo(self.presinfo)
         self.content = []
         self.presinfo = presinfo
 
+# Simple container for whole layout.
+class Layout(object):
+    def __init__(self):
+        self.content = []
+
 
 def _layout_column_width(col):
     """
     else:
         return 1
 
-def _layout_column_count(row):
-    """
-    Get the number of logical columns in a LayoutRow
-    """
-    return sum(_layout_column_width(c) for c in row.content)
-
 def is_root(node):
     return node.tag == 'html' or node.tag == 'body'
 
     command_info = _find_layout_commands(root, structure, styleinfo)
 
     # Build a Layout structure.
-    # a column is fine for a top level container, as it has a 'contents' attribute
-    layout = LayoutColumn()
+    layout = Layout()
 
     # Get nodes
     nodes = root.getchildren()
             else:
                 _trim_empty_layout(l)
 
-def _check_layout(layout, structure, layout_strategy):
-    sect_dict = dict((si.node, si) for si in structure)
+def _check_layout(row, structure, layout_strategy, sect_dict=None):
+    if sect_dict is None:
+        sect_dict = dict((si.node, si) for si in structure)
     max_cols = layout_strategy.max_columns
-    for row in layout.content:
-        # Cope with NodeContent:
-        if not hasattr(row, 'content'):
-            continue
-        # TODO - need to check nested layout structures
 
-        if _layout_column_count(row) > max_cols:
-            # Because columns can be multiple width, we can't easily work out
-            # which column needs to be moved, so just refer user to whole
-            # section.
+    # Cope with NodeContent:
+    if not hasattr(row, 'content'):
+        return
 
-            nodes = row.content[0].content[0].as_nodes(layout_strategy)
-            while True:
-                # nodes[0] might be a div created for layout.  If so, it won't
-                # be in sect_dict. But one of its children will be.
-                sect = sect_dict.get(nodes[0], None)
-                if sect is not None:
-                    break
-                else:
-                    nodes = nodes[0]
+    if row.column_count() > max_cols:
+        # Because columns can be multiple width, we can't easily work out
+        # which column needs to be moved, so just refer user to whole
+        # section.
 
-            raise TooManyColumns("The maximum number of columns is %(max)d. "
-                                 "Please adjust columns in section '%(name)s'." %
-                                 dict(max=max_cols, name=sect.name))
+        nodes = row.content[0].content[0].as_nodes(layout_strategy)
+        while True:
+            # nodes[0] might be a div created for layout.  If so, it won't
+            # be in sect_dict. But one of its children will be.
+            sect = sect_dict.get(nodes[0], None)
+            if sect is not None:
+                break
+            else:
+                nodes = nodes[0]
+
+        raise TooManyColumns("The maximum number of columns is %(max)d. "
+                             "Please adjust columns in section '%(name)s'." %
+                             dict(max=max_cols, name=sect.name))
+
+    for col in row.content:
+        # Check nested layouts.
+        for content in col.content:
+            _check_layout(content, structure, layout_strategy, sect_dict=sect_dict)
+
 
 def preview_html(html, pres):
     root, structure = format_html(html, pres, return_tree=True)