Пример #1
0
        /// <summary>
        /// Split this layout at the position determined during an earlier call to
        /// AssessPageBreak. Moves sublayouts below the split into a new layout
        /// and returns that new layout.
        /// </summary>
        public override Layout DoPageBreak()
        {
            using (new TraceContextPusher(_generator, _traceContext))
            {
                Trace("split index {0}", _pageSplitIndex);

                //	If we come here then we're either splitting or moving entirely to
                //	the next page. This situation could be caused by either the bullet
                //	or the content being too long to fit on the current page. We never
                //	split the bullet, and the bullet and content are always top-aligned,
                //	so if it's the bullet that's too long then we want to move entirely
                //	to the next page, regardless of the length of the content. In either
                //	case we want to split the content (possibly leaving the first half
                //	of the split empty) and duplicate the bullet (leaving either the
                //	original or the copy empty).

                //	Create a copy of ourself
                ListItemLayout lower = (ListItemLayout)ShallowCopy();

                //	Split our content and move the lower half to the copy
                Layout contentCopy = _contentLayout.DoPageBreak();
                lower.AddSubLayout(contentCopy);
                lower._contentLayout = contentCopy;

                //	If the content was moved entirely to the next page, leaving the
                //	original content layout empty, then the copy needs a valid and fully
                //	functional bullet. If the content was split then the copy doesn't
                //	need a visible bullet, and shouldn't be capable of being renumbered,
                //	but everything's a lot easier if we give it an empty bullet layout
                //	anyway.
                Layout bulletCopy = null;
                if (!_contentLayout.IsEmpty())                // content was split
                {
                    bulletCopy = new TextLayout("", null, _generator, _trackingInfo.LineNumber, _trackingInfo.LinePosition);
                }
                else
                {
                    bulletCopy = _bulletLayout.DeepCopy();
                }
                lower.AddSubLayout(bulletCopy);
                lower._bulletLayout = bulletCopy;

                return(lower);
            }
        }
Пример #2
0
        public override void RemoveEmptyLayouts()
        {
            base.RemoveEmptyLayouts();

            //	Renumber our list items to fill in any gaps left by removed items
            int number = _style.BulletStyle.StartAt;

            foreach (Layout layout in _subLayouts)
            {
                if (!layout.IsEmpty())
                {
                    ListItemLayout item = layout as ListItemLayout;
                    //	If a list item has been split across a page break then we
                    //	only want to renumber its upper half
                    if (item.HasBullet)
                    {
                        item.Renumber(number++);
                    }
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Wrap all our sublayouts in ListItemLayouts.
        /// </summary>
        private List <Layout> WrapSublayouts(List <Layout> unwrapped)
        {
            List <Layout> wrapped = new List <Layout>();
            int           number  = _style.BulletStyle.StartAt;

            foreach (Layout layout in unwrapped)
            {
                ListItemLayout item = null;
                if (layout is ListItemLayout)
                {
                    item = (ListItemLayout)layout;                     // already wrapped
                }
                else
                {
                    item = new ListItemLayout(layout, _style, number++,
                                              _generator, _trackingInfo.LineNumber, _trackingInfo.LinePosition, _traceContext);
                }
                wrapped.Add(item);
            }
            return(wrapped);
        }
Пример #4
0
        /// <summary>
        /// Evalute page break rules for within a single item in the list.
        /// </summary>
        private bool EvaluateItemPageBreakRules(Position position, ListItemLayout item, PageLayout pageLayout)
        {
            //	If we're outside the page's body box then we're not body text, and
            //	so we don't apply page break rules
            if (!pageLayout.BodyBox.Contains(position))
            {
                return(false);
            }

            //	If we're already on a new page then there's nothing to do. Even if
            //	our rules said that we don't have enough room, we can't fix that
            //	by creating another page.
            if (position.Y >= pageLayout.BodyBox.Top)
            {
                return(false);
            }

            //	If we have our own rules then use them, otherwise if the current
            //	page has rules the use them, otherwise use none
            PageBreakRules rules = item.PageBreakRules;

            if (rules == null)
            {
                rules = pageLayout.PageBreakRules;
            }
            if (rules == null)
            {
                rules = _defaultItemPageBreakRules;
            }


            //--------------------------------------------------------
            //	1.	New-page rule
            if (rules.NewPage)
            {
                return(true);
            }


            //--------------------------------------------------------
            //	2.	Keep-with-next rule


            //--------------------------------------------------------
            //	3.	Max-position rule

            //	Our current position is an offset from the bottom of the page, not
            //	from the bottom of the body box, so subtract the body box bottom
            //	to recalibrate the calculations to start at zero.
            int y = position.Y - pageLayout.BodyBox.Bottom;

            //	Our position is measured from the bottom, but the rule is expressed
            //	in terms where zero is at the top, so invert position.
            y = pageLayout.BodyBox.Height - y;

            //	Convert the position to a percentage
            float percent = (float)y / (float)pageLayout.BodyBox.Height;

            //	Now check the rule
            if (percent > rules.MaximumPosition)
            {
                return(true);
            }


            //--------------------------------------------------------
            //	4.	Min-lines rule

            //	Work out the height we need to draw our minimum start lines.
            //	If it's greater than the space available on the page then
            //	start a new page.
//			int minLines = item.Lines.Count > rules.MinimumLines ? rules.MinimumLines : item.Lines.Count;
//			int minStartHeight = 0;
//			for(int x = 0; x < minLines; ++x)
//			{
//				int lineHeight = item.Lines[x].Height;
//				minStartHeight += lineHeight;
//			}
//			if(position.Y < pageLayout.BodyBox.Bottom + (_style.Padding?.Bottom ?? 0) + (_style.ItemStyle.Padding?.Bottom ?? 0) + minStartHeight)
//				return true;


            //--------------------------------------------------------
            //	No rule said that we need a break, so stay on the current page
            return(false);
        }
Пример #5
0
        private void RenderListItem(ListItemLayout layout, IContentContainer container)
        {
            //	A list item, which is based on a single design layout, can
            //	include any number of design paragraphs introduced by embedded
            //	HTML <p> tags. To render these as a single item in the Word
            //	list, they must all be rendered as a single Word paragraph.
            //	We achieve this by concatenating all the design paragraphs
            //	together, with double line break separators. The first line
            //	break starts a new line, and the second inserts some whitespace.
            //
            //	A nested list is introduced by a group layout, which is a single
            //	item in the current list and which contains its own list.
            //
            //	We only support text content in list items - no photos.
            //
            //	So the list item layout's content sublayout is always either
            //	a text layout or a group layout. And the list item is always
            //	a single Word paragraph.

            //	The item style is to be found in the item's list's style
            s.ListStyle listStyle           = (s.ListStyle)layout.Style;
            s.TextStyle itemStyle           = listStyle.ItemStyle;
            IParagraph  paragraph           = container.AddParagraph(itemStyle, layout.TrackingInfo);
            int         numberingInstanceId = _numberingInstances.Peek();     // stack guaranteed not to be empty

            paragraph.SetNumbering(numberingInstanceId, _numberingLevel);

            switch (layout.ContentLayout.LayoutType)
            {
            case LayoutType.Text:
            {
                TextLayout   contentLayout = (TextLayout)layout.ContentLayout;
                List <Verse> verses        = contentLayout.GetFormattedText();
                if (verses == null)
                {
                    break;
                }
                if (verses.Count == 0)
                {
                    break;
                }
                foreach (Verse verse in verses)
                {
                    if (verse is ParagraphVerse)
                    {
                        //	Two line breaks to look like a new paragraph without actually
                        //	being a new Word paragraph. But don't do this if it's the first
                        //	verse.
                        if (verse == verses[0])
                        {
                            continue;
                        }
                        paragraph.AddLineBreak();
                        paragraph.AddLineBreak();
                    }
                    else if (verse is LineBreakVerse)
                    {
                        paragraph.AddLineBreak();
                    }
                    else
                    {
                        paragraph.AddRun(verse.Text, verse.Format.Font, verse.Format.Color);
                    }
                }
                break;
            }

            case LayoutType.Group:
            {
                foreach (Layout sublayout in layout.ContentLayout.SubLayouts)
                {
                    Render(sublayout, container);
                }
                break;
            }

            default:
            {
                break;
            }
            }
        }
Пример #6
0
 private void RenderListItemLayout(ListItemLayout layout, Page page)
 {
     Render(layout.BulletLayout, page);
     Render(layout.ContentLayout, page);
 }
Пример #7
0
 public ListItemLayout(ListItemLayout src)
     : base(src)
 {
     _number    = src._number;
     _listStyle = src._listStyle;
 }