Update pane heights and widths based on the current window and their desired geometry.

        What to bear in mind:
          Panes may have a fixed desired size.
          Panes may be set to expand maximally on either axis.
          Panes may be set to fit to the sum of their content buffers (accounting for alignment).
          Panes may be set to float.
          Two panes set to float and expand on the same axis will not overlap.
          EXPANDing panes may be adjacent to non-floating self-coordinating panes...

        Two panes wanting a height of ten each on a five line window will overflow offscreen.
        Using FIT for an axis on an undersized Window will also overflow offscreen.

def calculate_pane_heights_and_widths(self):
        """
        Update pane heights and widths based on the current window and their desired geometry.

        What to bear in mind:
          Panes may have a fixed desired size.
          Panes may be set to expand maximally on either axis.
          Panes may be set to fit to the sum of their content buffers (accounting for alignment).
          Panes may be set to float.
          Two panes set to float and expand on the same axis will not overlap.
          EXPANDing panes may be adjacent to non-floating self-coordinating panes...

        Two panes wanting a height of ten each on a five line window will overflow offscreen.
        Using FIT for an axis on an undersized Window will also overflow offscreen.

        """
        # Do a pass for heights
        # Every pane must be represented in order to map properly later
        growing_panes      = []
        claimed_columns    = 0
        for v_index, element in enumerate(self.panes):
            # Get maximal height from panes in sublists
            if type(element) == list:
                expanding_in_sublist = [] # A list we'll append to growing_panes
                claimed_from_sublist = [] # The heights gleaned from this pass
                for h_index, pane in enumerate(element):
                    if pane.hidden: continue

                    # Let height be max L/R distance from top if self-coordinating
                    if pane.coords and pane.self_coordinating:
                        pane.height = max([pane.coords[1][0][0],pane.coords[1][1][0]])
                        claimed_from_sublist.append(pane.height)
                        continue

                    if len(pane.geometry) < 2:
                        pane.height = 0
                        continue

                    desired_height = pane.geometry[1]

                    if isinstance(desired_height, int):
                        pane.height = desired_height
                        claimed_from_sublist.append(pane.height)
                        continue

                    elif isinstance(desired_height, str):
                        # Calculate the width of panes set to FIT
                        if desired_height == FIT:
                            buffer = ""
                            for frame in pane.content:
                                buffer += frame[0]
                            pane.height = len(buffer.split('\n'))
                            claimed_from_sublist.append(pane.height)
                            continue

                        elif desired_height == EXPAND:
                            expanding_in_sublist.append(pane)
                            continue

                    pane.height = desired_height

                # Append any expanding panes to growing_panes as a list
                if expanding_in_sublist:
                    growing_panes.append(expanding_in_sublist)

                # The total claimed columns for this sublist:
                if claimed_from_sublist:
                    claimed_columns += max(claimed_from_sublist)
            else:
                if element.hidden: continue

                if element.coords and element.self_coordinating:
                    element.height = max([element.coords[1][0][0], element.coords[1][1][0]])
                    claimed_columns += element.height
                    continue

                if len(element.geometry) < 2:
                    element.height = 0
                    continue

                desired_height = element.geometry[1]

                if isinstance(desired_height, int):
                    element.height = desired_height
                    claimed_columns += element.height
                    continue

                elif isinstance(desired_height, str):
                    # Calculate the width of panes set to FIT
                    if desired_height == FIT:
                        buffer = ""
                        for frame in element.content:
                            buffer += frame[0]
                        element.height = len(buffer.split('\n'))
                        claimed_columns += element.height
                        continue

                    elif desired_height == EXPAND:
                        growing_panes.append(element)
                        continue

        # Calculate how many rows are left by panes with fixed heights
        if growing_panes:
            g = len(growing_panes)
            remaining_space = self.height - claimed_columns
            typical_expanse = remaining_space / g
            tracking = 0
            rmg = remaining_space % g


            # Calculate adjustments if the height isn't evenly shared
            for i, pane in enumerate(growing_panes):
                if isinstance(pane, list):
                    for k,p in enumerate(pane):
                        p.height = typical_expanse
                        if not i:
                            # Account for claimed space
                            for x in range(len(growing_panes)):
                                if rmg == x:
                                    p.height -= len(growing_panes) - (x+1)

                            # Adjust for an extra column that can't be evenly shared
                            if self.height % 2:
                                if not claimed_columns:
                                    p.height += 1
                                else:
                                    p.height -= claimed_columns
                            else:
                                p.height -= claimed_columns
                        if not k:
                            tracking += p.height
                else:
                    pane.height = typical_expanse
                    if not i:
                        for x in range(len(growing_panes)):
                            if rmg == x:
                                pane.height -= len(growing_panes) - (x+1)
                        if self.height % 2:
                            if not claimed_columns:
                                pane.height += 1
                            else:
                                pane.height -= claimed_columns
                        else:
                            pane.height -= claimed_columns

                    tracking += pane.height

        #s = "Growing rows: %i, %s number of rows: %s, claimed: %i, remaining: %i, remaining/growing: %i,rmodg: %i" % \
        #    (g, "odd" if self.height % 2 else "even", self.height, claimed_columns,remaining_space, typical_expanse, remaining_space%g)
#        self.addstr(self.height-1, self.width-len(s),s)

        # Then a pass for widths.
        for v_index, element in enumerate(self.panes):
            claimed_rows    = 0
            growing_panes   = []
            # Get panes who will be sharing the x axis
            if type(element) == list:
                for h_index, pane in enumerate(element):
                    if pane.hidden: continue

                    # Calculate the widest part of a self-coordinating pane
                    if pane.coords and pane.self_coordinating:
                        rightmost = [pane.coords[0][1][1],pane.coords[1][1][1]]
                        pane.width = max(rightmost)
                        continue

                    if not pane.geometry:
                        pane.width = 0
                        continue

                    desired_width = pane.geometry[0]

                    if isinstance(desired_width, int):
                        claimed_rows += desired_width
                        pane.width = desired_width
                        continue

                    elif isinstance(desired_width, str):
                        # Calculate the width of panes set to FIT
                        if desired_width == FIT:
                            buffer = ""
                            for frame in pane.content:
                                buffer += frame[0]
                            pane.width = max(map(len, buffer.split('\n')))
                            claimed_rows += pane.width
                            continue

                        elif desired_width == EXPAND:
                            growing_panes.append(pane)
                            continue

            else:

                if element.hidden: continue

                if not element.geometry:
                    element.width = 0
                    continue

                desired_geometry = element.geometry[0]

                if element.coords and element.self_coordinating:
                    rightmost = [element.coords[0][1][1],element.coords[1][1][1]]
                    element.width = max(rightmost)
                    continue

                if isinstance(desired_geometry, int):
                    element.width = desired_geometry
                    continue

                if isinstance(desired_geometry, str):
                    if desired_geometry == FIT:
                        buffer = ""
                        for frame in element.content:
                            buffer += frame[0]
                        element.width = max(map(len, buffer.split('\n')))
                    elif desired_geometry == EXPAND:
                        element.width = self.width

            # Calculate the space to be shared between panes set to EXPAND
            remaining_space = self.width - claimed_rows
            for pane in growing_panes:
                pane.width = remaining_space / len(growing_panes)

        # Grant the rightmost panes an extra row if self.width is uneven:
        if self.width % 2:
            for pane in self.panes:
                if isinstance(pane, list):
                    for i, p in enumerate(reversed(pane)):
                        if i == 0 and not p.self_coordinating and p.geometry \
                                and p.geometry[0] == EXPAND and not p.hidden:
                                p.width += 1
                else:                        
                    if not pane.self_coordinating and pane.geometry \
                        and pane.geometry[0] == EXPAND and not pane.hidden:
                        pane.width += 1
                        continue

        if self.debug:
            self.addstr(self.height-5, 0, "Window height: " + str(self.height))
            self.addstr(self.height-4, 0, "Window width:  " + str(self.width))
            self.addstr(self.height-2, 0, "Heights: " + str([p.height for p in self]))
            self.addstr(self.height-1, 0, "Widths:  " + str([p.width for p in self]))