/// <summary> /// Lays out all the contents of the list item in the current itemblock and returns the used height of the /// components it has laid out. /// </summary> /// <param name="entry"></param> /// <returns></returns> private PDFUnit LayoutItemContent(ListNumberEntry entry) { ComponentList contents = null; IPDFContainerComponent container = entry.ListItem as IPDFContainerComponent; PDFUnit avail = _itemblock.CurrentRegion.AvailableHeight; if (container.HasContent) { //because we are mimicing being the container - set the full style to the item style Style last = this.FullStyle; this.FullStyle = entry.FullStyle; contents = container.Content; this.DoLayoutChildren(contents); //And restore the full style to the previous item after. this.FullStyle = last; } this._itemblock.CurrentRegion.CloseCurrentItem(); // Calculate the height used and return PDFUnit newAvail = _itemblock.CurrentRegion.AvailableHeight; PDFUnit used = avail - newAvail; return(used); }
/// <summary> /// Layout the entry item number and returns the height used by the item number. /// </summary> /// <param name="entry">The entry whose number should be laid out</param> /// <returns></returns> private PDFUnit LayoutItemNumber(ListNumberEntry entry, Style fullstyle) { ListItem item = entry.ListItem; PDFUnit avail = _itemblock.CurrentRegion.AvailableHeight; ListItemLabel literal = (ListItemLabel)entry.NumberComponent; Style applied = literal.GetAppliedStyle(); if (null != applied) { this.StyleStack.Push(applied); fullstyle = this.StyleStack.GetFullStyle(literal); } //Get the text of the next number if (string.IsNullOrEmpty(entry.NumberText)) { literal.Text = this.Component.Document.ListNumbering.Increment(); } else { literal.Text = entry.NumberText; } //Set the list items label reference for future use if required. item.ItemLabelComponent = entry.NumberComponent; //Actually layout the item in the region this.DoLayoutAChild(item.ItemLabelComponent, fullstyle); this._itemblock.CurrentRegion.CloseCurrentItem(); // Calculate the height used and return PDFUnit newAvail = _itemblock.CurrentRegion.AvailableHeight; PDFUnit used = avail - newAvail; if (null != applied) { this.StyleStack.Pop(); } return(used); }
/// <summary> /// Lays out a single list item based on the entry, and the list position options /// </summary> /// <param name="index"></param> /// <param name="entry"></param> /// <param name="listPosOpts"></param> /// <returns></returns> private PDFUnit LayoutAnItem(int index, ListNumberEntry entry, PDFPositionOptions listPosOpts) { //restore the items applied style onto the stack this.StyleStack.Push(entry.AppliedStyle); Style full = entry.FullStyle; PDFUnit numberWidth = entry.NumberWidth; PDFArtefactRegistrationSet artefacts = entry.ListItem.RegisterLayoutArtefacts(this.Context, full); PDFPositionOptions itemopts = full.CreatePostionOptions(); PDFUnit pageHeight = this.Context.DocumentLayout.CurrentPage.Height; PDFUnit h = pageHeight; PDFUnit w = _listBlock.AvailableBounds.Width; PDFUnit y = _itemoffset; PDFUnit alley = DefaultListItemAlley; if (itemopts.HasAlleyWidth) { alley = itemopts.AlleyWidth; } else if (listPosOpts.HasAlleyWidth) { alley = listPosOpts.AlleyWidth; } if (itemopts.Height.HasValue) { h = itemopts.Height.Value; } else if (itemopts.Margins.IsEmpty == false) { h -= itemopts.Margins.Top + itemopts.Margins.Bottom; } h -= itemopts.Padding.Top + itemopts.Padding.Bottom; if (itemopts.Width.HasValue) { w = itemopts.Width.Value; } else if (itemopts.Margins.IsEmpty == false) { w -= itemopts.Margins.Left + itemopts.Margins.Right; } w -= itemopts.Padding.Left + itemopts.Padding.Right; PDFRect totalBounds = new PDFRect(PDFUnit.Zero, y, w, h); this._itemblock = _listBlock.BeginNewContainerBlock(entry.ListItem, this, full, itemopts.PositionMode); PDFColumnOptions colOpts = new PDFColumnOptions() { AlleyWidth = alley, AutoFlow = false, ColumnCount = 2 }; this._itemblock.InitRegions(totalBounds, itemopts, colOpts, this.Context); //Alter the widths of the regions to allow for only the number width PDFRect region1bounds = this._itemblock.Columns[0].TotalBounds; PDFUnit difference = region1bounds.Width - numberWidth; region1bounds.Width = numberWidth; this._itemblock.Columns[0].TotalBounds = region1bounds; this._itemblock.Columns[0].HAlignment = entry.NumberAlignment; PDFRect region2Bounds = this._itemblock.Columns[1].TotalBounds; if (region2Bounds.X > 0) { region2Bounds.X -= difference; } region2Bounds.Width += difference; this._itemblock.Columns[1].TotalBounds = region2Bounds; PDFUnit numberHeight = this.LayoutItemNumber(entry, full); this._itemblock.CurrentRegion.Close(); bool success = this._itemblock.MoveToNextRegion(true, PDFUnit.Zero, this.Context); //Pass Zero as we are not interested in overflowing yet PDFUnit contentHeight = this.LayoutItemContent(entry); //check that we can fit - addind the margins and padding back in. PDFUnit itemHeight = PDFUnit.Max(numberHeight, contentHeight); if (itemopts.Height.HasValue) { itemHeight = itemopts.Height.Value; } else if (itemopts.Margins.IsEmpty == false) { itemHeight += itemopts.Margins.Top + itemopts.Margins.Bottom; } itemHeight += itemopts.Padding.Top + itemopts.Padding.Bottom; if (itemHeight > this._listBlock.AvailableBounds.Height - _itemoffset) { PDFLayoutBlock origparent = this.CurrentBlock; PDFLayoutRegion origregion = this.CurrentBlock.CurrentRegion; PDFLayoutBlock origlist = this._listBlock; PDFLayoutBlock origItem = this._itemblock; if (this._listBlock.Position.OverflowSplit == OverflowSplit.Never) { if (this.MoveFullListToNextRegion(_itemoffset + itemHeight)) { //_itemoffset += itemHeight; //PDFRect avail = _listBlock.AvailableBounds; //avail.Height = avail.Height - _itemoffset; } else { this.Context.TraceLog.Add(TraceLevel.Warning, LOG_CATEGORY, "List '" + this.List.UniqueID + "' has filled the available space, and cannot overflow onto a new region. Layout has stopped at item index " + index); this.ContinueLayout = false; return(0); } } else if (this.StartListInAnotherRegion(itemHeight, origItem, index)) { //origregion.AddToSize(origlist); _itemoffset = 0; origItem.Offset(0, 0); } else { (origItem.Parent as PDFLayoutBlock).CurrentRegion.RemoveItem(origItem); this.Context.TraceLog.Add(TraceLevel.Warning, LOG_CATEGORY, "List '" + this.List.UniqueID + "' has filled the available space, and cannot overflow onto a new region. Layout has stopped at item index " + index); this.ContinueLayout = false; } } else if (this._itemblock.CurrentRegion.IsClosed) { this._itemblock = this.CurrentBlock.LastOpenBlock(); this._listBlock = this._itemblock.Parent as PDFLayoutBlock; } if (null != this._itemblock) { if (this._itemblock.CurrentRegion.IsClosed == false) { this._itemblock.CurrentRegion.Close(); } if (this._itemblock.IsClosed == false) { this._itemblock.Close(); this._listBlock.CurrentRegion.AddToSize(this._itemblock); } } if (this.ContinueLayout) { RegisterChildLayout(entry.ListItem); } if (null != artefacts) { entry.ListItem.CloseLayoutArtefacts(this.Context, artefacts, full); } this.StyleStack.Pop(); return(itemHeight); }
// // List entry building // #region private int BuildListEntries(PDFListStyle style, out PDFUnit width) /// <summary> /// Builds all the ListNumberEntries for all the ListItems in this lists items and stores /// them in a reference in this engine /// </summary> /// <param name="style"></param> /// <param name="width"></param> /// <returns></returns> private int BuildListEntries(out PDFUnit width) { int index = 0; HorizontalAlignment halign = this.FullStyle.GetValue(StyleKeys.ListAlignmentKey, DefaultListItemAlignment); PDFUnit defaultWidth = this.FullStyle.GetValue(StyleKeys.ListInsetKey, Const.DefaultListNumberInset); width = defaultWidth; this._entries = new List <ListNumberEntry>(); foreach (ListItem item in this.List.Items) { if (item.Visible) { Style applied, full; if (string.IsNullOrEmpty(item.DataStyleIdentifier) || !this.DocumentLayout.TryGetStyleWithIdentifier(item.DataStyleIdentifier, out applied, out full)) { this.Context.PerformanceMonitor.Begin(PerformanceMonitorType.Style_Build); applied = item.GetAppliedStyle(); this.StyleStack.Push(applied); full = this.StyleStack.GetFullStyle(item); if (!string.IsNullOrEmpty(item.DataStyleIdentifier)) { this.DocumentLayout.SetStyleWithIdentifier(item.DataStyleIdentifier, applied, full); } this.Context.PerformanceMonitor.End(PerformanceMonitorType.Style_Build); } else { this.StyleStack.Push(applied); } if (full.Position.PositionMode == PositionMode.Invisible) { this.StyleStack.Pop(); if (this.Context.ShouldLogDebug) { this.Context.TraceLog.Add(TraceLevel.Debug, "Layout", "Skipping over the layout of list item '" + item.UniqueID + "' as it is invisible"); } continue; } PDFUnit itemWidth; ListNumberingGroupStyle numberStyle; HorizontalAlignment itemHAlign = halign; string text; Component itemNumber = BuildAListNumberComponent(item, full, ref itemHAlign, out numberStyle, out itemWidth, out text); if (itemWidth < PDFUnit.Zero) { itemWidth = defaultWidth; } else { width = PDFUnit.Max(width, itemWidth); } ListNumberEntry entry = new ListNumberEntry() { NumberComponent = itemNumber, NumberGroupStyle = numberStyle, ListItem = item, NumberWidth = itemWidth, FullStyle = full, AppliedStyle = applied, NumberIndex = index, NumberAlignment = itemHAlign, NumberText = text }; this._entries.Add(entry); index++; this.StyleStack.Pop(); } } return(index); }