/// <summary>
        /// Assess how to handle a page break.
        /// </summary>
        public override PageDisposition AssessPageBreak(Rectangle bodyBox)
        {
            using (new TraceContextPusher(_generator, _traceContext))
            {
                Trace("_bounds={0} bodyBox={1}", _bounds, bodyBox);
                PageDisposition disposition = PageDisposition.ThisPage;

                //	We never split the bullet, so if the bullet doesn't fit on the
                //	page then we need to move entirely to the next page
                disposition = _bulletLayout.AssessPageBreak(bodyBox);
                if (disposition != PageDisposition.ThisPage)
                {
                    return(PageDisposition.NewPage);
                }

                //	We're happy to split our content and duplicate the bullet
                disposition = _contentLayout.AssessPageBreak(bodyBox);
                return(disposition);
            }
            //	ListItemLayout doesn't have to worry about keep-with-next because
            //	keep-with-next is implemented by the container layout, and the
            //	list item layout doesn't really have sublayouts. The bullet and
            //	content layouts are technically sublayouts but they don't function
            //	as such.
        }
示例#2
0
 protected override PageDisposition SetPageSplitIndex(Rectangle bodyBox, ref bool honourKeepWithNext)
 {
     using (new TraceContextPusher(_generator, _traceContext))
     {
         PageDisposition disposition = PageDisposition.ThisPage;
         if (_bounds.Bottom < bodyBox.Bottom)
         {
             disposition = PageDisposition.Overflow;
         }
         //	Our bottom padding has already been factored in by Layout.AssessPageBreak
         return(disposition);
     }
 }
示例#3
0
        protected override PageDisposition SetPageSplitIndex(Rectangle bodyBox, ref bool honourKeepWithNext)
        {
            using (new TraceContextPusher(_generator, _traceContext))
            {
                PageDisposition disposition = base.SetPageSplitIndex(bodyBox, ref honourKeepWithNext);

                //	Don't split the header rows
                if (_pageSplitIndex < _headerRows)
                {
                    _pageSplitIndex = _headerRows;
                }

                return(disposition);
            }
        }
        public override PageDisposition AssessPageBreak(Rectangle bodyBox)
        {
            using (new TraceContextPusher(_generator, _traceContext))
            {
                Trace("_bounds={0} bodyBox={1}", _bounds, bodyBox);
                PageDisposition disposition = PageDisposition.ThisPage;

                //	If we don't fit on this page then split
                if (_bounds.Bottom < bodyBox.Bottom)
                {
                    disposition = PageDisposition.Split;
                }

                Trace("return {0}, split index {1}", disposition, _pageSplitIndex);
                return(disposition);
            }
        }
示例#5
0
        public override PageDisposition AssessPageBreak(Rectangle bodyBox)
        {
            //	We override this method here because a table row's sublayouts
            //	are arranged horizontally, not vertically, and so their
            //	individual dispositions interact with each other. For example,
            //	if one cell wants to split but another refuses, then the row
            //	cannot split. Or if any one cell wants to go on the next page
            //	then the entire row goes on the next page.
            //
            //	Keep-with-next is meaningless in a table row because the next
            //	sublayout is another cell on the same row, and by definition
            //	all cells start on the same page.

            using (new TraceContextPusher(_generator, _traceContext))
            {
                Trace("_bounds={0} bodyBox={1}", _bounds, bodyBox);
                PageDisposition disposition = PageDisposition.ThisPage;

                //	If we've got a new-page rule then put ourself on the next page
                if (_pageBreakRules?.NewPage ?? false)
                {
                    Trace("page break rules say new-page, so set new-page disposition");
                    disposition = PageDisposition.NewPage;
                }

                if (disposition == PageDisposition.ThisPage)
                {
                    //	If we've got a max-position rule then check whether we're past
                    //	that position. And if we don't have a max-position rule then
                    //	assume a max position of 1.0 so that we don't position ourself
                    //	off the bottom of the page.
                    float maxPosition = _pageBreakRules?.MaximumPosition ?? 1.0f;
                    if (maxPosition > 1.0f)
                    {
                        maxPosition = 1.0f;
                    }

                    //	Express the distance from the top of the body box to the top
                    //	of ourself, as a percentage of the body box height
                    float position = ((float)(bodyBox.Top - _bounds.Top)) / (float)bodyBox.Height;
                    if (position > maxPosition)
                    {
                        Trace(
                            "max-position {0} rule is violated by bounds {1}, so set overflow disposition",
                            maxPosition, _bounds);
                        disposition = PageDisposition.Overflow;
                    }
                }

                //	If it looks like we can start on this page then ask our sublayouts
                //	what they want to do. Even if we think that we can fit entirely on
                //	this page, a sublayout could have rules that cause it to move to the
                //	next page and that would cause us to split.
                //	Min-lines is evaluated on splitting.
                if (disposition == PageDisposition.ThisPage)
                {
                    List <PageDisposition> sublayoutDispositions = new List <PageDisposition>();
                    foreach (Layout sublayout in _subLayouts)
                    {
                        PageDisposition sublayoutDisposition = sublayout.AssessPageBreak(bodyBox);
                        sublayoutDispositions.Add(sublayoutDisposition);
                    }

                    //	If any one cell said next-page then put the entire row on the next page
                    if (sublayoutDispositions.Contains(PageDisposition.NewPage))
                    {
                        Trace("at least one cell says next-page, so set new-page disposition");
                        disposition = PageDisposition.NewPage;
                    }
                    else if (sublayoutDispositions.Contains(PageDisposition.Split))
                    {
                        //	If no cell said next-page, and any one said split, then split.
                        //	(If any cell couldn't fit on this page but wasn't prepared to
                        //	split then it would have said next-page. So we know that all
                        //	cells are content to split.)
                        Trace("at least one cell says split, so set split disposition");
                        bool canSplit = CanSplit(bodyBox);
                        if (canSplit)
                        {
                            disposition = PageDisposition.Split;
                        }
                        else
                        {
                            Trace("need to split but can't, so set overflow disposition");
                            _pageSplitIndex = 0;
                            disposition     = PageDisposition.Overflow;
                        }
                    }
                }

                Trace("return {0}, split index {1}", disposition, _pageSplitIndex);
                return(disposition);
            }
        }
示例#6
0
        private PageLayout ApplyPageBreak()
        {
            //	Collapse any space layouts at the top of the page. Space layouts are
            //	intended to provide space _between_ layouts and thus are not appropriate
            //	at the top of a page. We collapse top space after drafting so that we know
            //	where the space layouts fall on this page, but before applying the next
            //	page break because lower layouts might now fit on this page.
            CollapseTopSpace();

            PageDisposition disposition = AssessPageBreak(_bodyBox);

            //	Avoid infinite overflow. If any layout starts at the top of the page and
            //	is longer than the page, then it will return disposition overflow or split
            //	and its page split index will be zero. Splitting at index zero is the same
            //	thing as overflowing. Overflowing a full page will cause this page to move
            //	all of its content onto a new page, leaving itself empty, and this will lead
            //	to infinite overflow. So just stop the overflow right now. This will give us
            //	an oversized page, but that's better than making a report with an infinite
            //	number of empty pages. (In the current implementation, AssessPageBreak here on
            //	a page layout will never return overflow because SetPageSplitIndex always
            //	converts overflow to split, and then because a page can split it doesn't convert
            //	it back to overflow. But for semantic clarity we still check for overflow here.)
            if ((disposition == PageDisposition.Overflow)
                ||
                (disposition == PageDisposition.Split && _pageSplitIndex == 0))
            {
                //	If we can split as requested then do so. Otherwise bump the page split
                //	index from zero to one - this will leave the oversized layout on this
                //	page but overflow subsequent layouts to the next. If it's not possible
                //	to bump the index then return an empty page to stop the overflow.
                Bump bump = BumpPageSplitIndex();
                switch (bump)
                {
                case Bump.Bumped:
                case Bump.Unnecessary:
                    //	The split index has been moved beyond zero (or was already there)
                    //	and so we can now do the normal page break. This may still leave
                    //	the oversized layout on this page, but later layouts are moved
                    //	to the next page.
                    break;

                case Bump.Impossible:
                    //	Couldn't fix the situation by splitting further down, so
                    //	just accept the oversized layout
                    return((PageLayout)ShallowCopy());
                }
            }

            PageLayout overflow = (PageLayout)DoPageBreak();

            //	This page now contains only the content that can fit in it. Content
            //	that must be moved to the next page, or a later page, is now contained
            //	in the overflow page. If the overflow page is empty then this is the last
            //	page.

            //	Redraft this page to set the layouts' bottoms so that they can
            //	draw borders correctly, and redraft the new page so that its contents
            //	start at the top of the page.
            Redraft(_bodyBox.Top);
            overflow?.Redraft(overflow._bodyBox.Top);
            return(overflow);
        }