diff --git a/PROMS/Volian.Print.Library/vlnParagraph.cs b/PROMS/Volian.Print.Library/vlnParagraph.cs index 9d1ac7f1..282e9f81 100644 --- a/PROMS/Volian.Print.Library/vlnParagraph.cs +++ b/PROMS/Volian.Print.Library/vlnParagraph.cs @@ -30,6 +30,7 @@ namespace Volian.Print.Library { int? bxIndex = null; vlnBox box = null; + float yTop = yoff; foreach (ItemInfo childItemInfo in itemInfoList) { int? bxIndx = childItemInfo.FormatStepData.StepLayoutData.STBoxindex; @@ -40,9 +41,9 @@ namespace Volian.Print.Library box = new vlnBox(); box.MyBox = new Box(); box.DefBox = vlnBox.BoxThin; - StepSectionLayoutData ssld = formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData; - int colR = int.Parse(formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.ColRTable.Split(",".ToCharArray())[childItemInfo.ColumnMode]); - int widS = vlnPrintObject.ToInt(formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.WidSTablePrint, maxRNO); + StepSectionLayoutData ssld = formatInfo.MyStepSectionLayoutData; + int colR = int.Parse(formatInfo.MyStepSectionLayoutData.ColRTable.Split(",".ToCharArray())[childItemInfo.ColumnMode]); + int widS = vlnPrintObject.ToInt(formatInfo.MyStepSectionLayoutData.WidSTablePrint, maxRNO); box.DefEnd = (float)(ssld.ColS + colR + widS + (60/4.8)); box.YOffset = yoff - .75F * vlnPrintObject.SixLinesPerInch; } @@ -119,6 +120,11 @@ namespace Volian.Print.Library else if (!MyItemInfo.IsStepSection) // Don't ouput the Step Section title { retval = DrawText(cb, ref yPageStart, yTopMargin, yBottomMargin, ref yLocation); + if (MyItemInfo.IsHigh) + { + MyPageHelper.VlnDestinations.Add(MyItemInfo.MyTab.CleanText + " " + MyItemInfo.DisplayText, + new PdfDestination(PdfDestination.FITBH,yLocation+YVeryTop-YTopMost+SixLinesPerInch)); + } } //Height = yLocation - retval; if (_PartsLeft != null && _PartsLeft.Count > 0) yPageStart = PartsLeft.ToPdf(cb, yPageStart, yTopMargin, yBottomMargin); @@ -134,15 +140,15 @@ namespace Volian.Print.Library float retval = yLocation; if (MyItemInfo.FormatStepData.CenterOneLineOnly && MyItemInfo.MyPrevious == null && MyItemInfo.NextItem == null && Height<(1.01F*IParagraph.Leading)) IParagraph.Alignment = Element.ALIGN_CENTER; - retval = Rtf2Pdf.TextAt(cb, IParagraph, XOffset, yLocation, Width, 100, PdfDebugText, yBottomMargin); + retval = Rtf2Pdf.TextAt(cb, IParagraph, XOffset, yLocation, Width, 100, DebugText, yBottomMargin); if (retval == 0) // problem occurred - paragraph was not able to be printed on page { // pagination logic needs to be fixed. cb.PdfDocument.NewPage(); - yPageStart = yTopMargin + YTop; + yPageStart = yTopMargin + YVeryTop; yLocation = yPageStart - YOffset; //MyItemInfo.ItemID, YSize, yPageSize, yLocation - Console.WriteLine("-1,'Yes','Forced Pagination',{0},{1},,{3},'{4}'", MyItemInfo.ItemID, YSize, 0, yLocation, MyItemInfo.ShortPath); - retval = Rtf2Pdf.TextAt(cb, IParagraph, XOffset, yLocation, Width, 100, PdfDebugText, yBottomMargin); + Console.WriteLine("-1,'Yes','Forced Pagination',{0},{1},,{3},{4}", MyItemInfo.ItemID, YSize, 0, yLocation, MyItemInfo.DBSequence); + retval = Rtf2Pdf.TextAt(cb, IParagraph, XOffset, yLocation, Width, 100, DebugText, yBottomMargin); } return retval; } @@ -160,16 +166,16 @@ namespace Volian.Print.Library if (roImage != null) { iTextSharp.text.Image it_image = iTextSharp.text.Image.GetInstance(roImage.Content); - retval = Rtf2Pdf.FigureAt(cb, it_image, XOffset + _CharsToTwips, yLocation, Width * MyPageHelper.YMultiplier, Height * MyPageHelper.YMultiplier, PdfDebugText, yBottomMargin, !MyItemInfo.FormatStepData.Type.Contains("Borderless")); + retval = Rtf2Pdf.FigureAt(cb, it_image, XOffset + _CharsToTwips, yLocation, Width * MyPageHelper.YMultiplier, Height * MyPageHelper.YMultiplier, DebugText, yBottomMargin, !MyItemInfo.FormatStepData.Type.Contains("Borderless")); } } return retval; } - private string PdfDebugText + private string DebugText { get { - return string.Format("DebugID = {0}, ID={1} Type={2} TypeName='{3}' EveryNLines={4} StepLevel={5}", DebugId, MyItemInfo.ItemID, MyItemInfo.FormatStepType, MyItemInfo.FormatStepData.Type, MyItemInfo.FormatStepData.StepLayoutData.EveryNLines, MyItemInfo.StepLevel); + return string.Format("DebugID = {0}, ID={1} Type={2} TypeName='{3}' StepLevel={4} DBSequence={5}", DebugId, MyItemInfo.ItemID, MyItemInfo.FormatStepType, MyItemInfo.FormatStepData.Type, MyItemInfo.StepLevel, MyItemInfo.DBSequence); } } public override float ToPdf(PdfContentByte cb, float yPageStart, float yTopMargin, float yBottomMargin) @@ -201,11 +207,14 @@ namespace Volian.Print.Library msg_yLocation = yBottomMargin + 2 * SixLinesPerInch; // 2 lines above bottom margin break; } - //float msg_yLocation = CalculateYOffset(yPageStart, yTopMargin); MyPageHelper.BottomMessage = new vlnText(cb, this, myMsg, myMsg, docstyle.Layout.LeftMargin + XOffsetBox + docstyle.Continue.Bottom.Margin ?? 0, msg_yLocation, MyItemInfo.ActiveFormat.PlantFormat.FormatData.Font); cb.PdfDocument.NewPage(); - yPageStart = yTopMargin + YTopMost - 2 * SixLinesPerInch; - msg_yLocation = CalculateYOffset(yPageStart, yTopMargin); + // If there is a box, adjust the yTopMost to include it. + // TODO: Why doesn't YTopMost account for the box? + float yTopMost = YTopMost; + //if (YVeryTop < yTopMost) Console.WriteLine("{0},{1},{2}", MyItemInfo.DBSequence, yTopMost, YVeryTop); + yTopMost = Math.Min(yTopMost,YVeryTop); + yPageStart = yTopMargin + yTopMost - 2 * SixLinesPerInch; myMsg = docstyle.Continue.Top.Message; if (myMsg.IndexOf(@"%d") > -1) myMsg = myMsg.Replace(@"%d", MyItemInfo.MyHLS.MyTab.CleanText.Trim()); @@ -252,7 +261,8 @@ namespace Volian.Print.Library vlnParagraphs process = new vlnParagraphs(null); foreach (vlnParagraph vPara in MyPageHelper.MyParagraphs.Values) { - if (!vPara.Processed && ((vPara.YOffset + vPara.Height) < YTopMost)) + //if (!vPara.Processed && ((vPara.YOffset + vPara.Height) < YTopMost)) + if (!vPara.Processed && ((vPara.YOffset) < YTopMost)) process.Add(vPara); } foreach (vlnParagraph vPara in process) @@ -260,25 +270,25 @@ namespace Volian.Print.Library vPara.ParagraphToPdf(cb, yPageStart, yTopMargin, yBottomMargin); } } - private static void WalkStepLevel(vlnParagraph para,float yTopMost) + private void WalkStepLevel(float yTopMost) { - foreach (vlnParagraph child in para.ChildrenAbove) - WalkStepLevel(child, yTopMost); - foreach (vlnParagraph child in para.ChildrenLeft) - WalkStepLevel(child, yTopMost); - ShowStepLevel(para,yTopMost); - foreach (vlnParagraph child in para.ChildrenRight) - WalkStepLevel(child, yTopMost); - foreach (vlnParagraph child in para.ChildrenBelow) - WalkStepLevel(child, yTopMost); + foreach (vlnParagraph child in ChildrenAbove) + child.WalkStepLevel(yTopMost); + foreach (vlnParagraph child in ChildrenLeft) + child.WalkStepLevel(yTopMost); + ShowStepLevel(yTopMost); + foreach (vlnParagraph child in ChildrenRight) + child.WalkStepLevel(yTopMost); + foreach (vlnParagraph child in ChildrenBelow) + child.WalkStepLevel(yTopMost); } - private static void ShowStepLevel(vlnParagraph para,float yTopMost) + private void ShowStepLevel(float yTopMost) { - ItemInfo item = para.MyItemInfo; + ItemInfo item = MyItemInfo; ItemInfo parent = item.ActiveParent as ItemInfo; - if (para.MyItemInfo.ItemID == 205) - Console.Write(""); - Console.WriteLine("'StepLevel',{0},{1},{2},{3},{4},{5},{6},{7},{8},{9}", para.YVeryTop - yTopMost, para.YSize, para.YBottomMost-yTopMost, item.ItemID, item.DBSequence, item.StepLevel, item.MyContent.Type % 10000, + //if (para.MyItemInfo.ItemID == 205) + // Console.Write(""); + Console.WriteLine("'StepLevel',{0},{1},{2},{3},{4},{5},{6},{7},{8},{9}", YVeryTop - yTopMost, YSize, YBottomMost-yTopMost, item.ItemID, item.DBSequence, item.StepLevel, item.MyContent.Type % 10000, parent.MyContent.Type % 10000, item.HasCautionOrNote ? 1 : 0, parent.Cautions == null ? 0 : 1); } private float _YVeryTop = -1; @@ -307,53 +317,267 @@ namespace Volian.Print.Library private int Paginate(float yLocation, float yTopMargin, float yBottomMargin) { float yPageSize = yTopMargin - yBottomMargin; - float yWithinMargins = CalculateYLocation(yLocation, yTopMargin) - yBottomMargin; + float yWithinMargins = CalculateYLocation(yLocation, yTopMargin) - yBottomMargin - SixLinesPerInch; + // if step is breaking over a number of pages, determine if the current step is the + // location of a pagebreak. + if (MyPageHelper.ParaBreaks.Count > 0) + { + if (this == MyPageHelper.ParaBreaks[0] || this.YTopMost > MyPageHelper.ParaBreaks[0].YTopMost) + { + MyPageHelper.ParaBreaks.RemoveAt(0); + //Console.WriteLine("'PageBreak',6,'Yes','Page Break within Step',{0},{1},{2},{3}, {4},'{5}'", MyItemInfo.ItemID, YSize, 0, 0, 0, MyItemInfo.ShortPath); + //Console.WriteLine("Prev = {0}", MyItemInfo.MyPrevious==null ? "''" : MyItemInfo.DBSequence); + ShowPageBreak(100,"Page Break within Step","Yes",YSize, yPageSize, yWithinMargins); + return 2; // break on this item within a step + } + return 0; // this is not an item with a break + } if (MyItemInfo.IsStepSection) return 0; // Don't Paginate on a Step Section + if (!MyItemInfo.IsHigh) return 0; // Don't Paginate on a Substep level + bool ManualPageBreak = (MyItemInfo.MyConfig as StepConfig).Step_ManualPagebreak; float mySize = YSize * MyPageHelper.YMultiplier; - if (mySize <= yWithinMargins) + string firstStep = "No"; + if (MyItemInfo.IsHigh && MyItemInfo.MyPrevious == null) + firstStep = "Yes"; + if (!ManualPageBreak && mySize <= yWithinMargins) // Don't Paginate if there is enough room, will fit on page { - if (MyItemInfo.IsHigh) - Console.WriteLine("'PageBreak',1,'No','HLS will fit on page',{0},{1},{2}, {3}, {4},'{5}'", MyItemInfo.ItemID, YSize, yPageSize, yWithinMargins, (int)(100 * yWithinMargins / yPageSize), MyItemInfo.ShortPath); - return 0; // Don't Paginate if there is enough room + //Console.WriteLine("'PageBreak',1,'No','HLS will fit on page',{0},{1},{2}, {3}, {4},'{5}'", MyItemInfo.ItemID, YSize, yPageSize, yWithinMargins, (int)(100 * yWithinMargins / yPageSize), MyItemInfo.ShortPath); + ShowPageBreak(-1, "HLS will fit on page", firstStep, YSize, yPageSize, yWithinMargins); + return 0; } - if (MyItemInfo.IsRNOPart && MyParent.XOffset < XOffset) return 0; // Don't paginate on an RNO to the right - if (MyItemInfo.IsHigh) + // !MyItemInfo.IsHigh - if (MyItemInfo.IsRNOPart && MyParent.XOffset < XOffset) return 0; // Don't paginate on an RNO to the right + if (YSize < yPageSize) // if the entire step can fit on one page, do a page break { - if (YSize < yPageSize) // if the entire step can fit on one page, do a page break - { - Console.WriteLine("'PageBreak',2,'Yes','HLS will fit on 1 Page',{0},{1},{2}, {3}, {4},'{5}'", MyItemInfo.ItemID, YSize, yPageSize, yWithinMargins, (int)(100 * yWithinMargins / yPageSize), MyItemInfo.ShortPath); - return 1; // Paginate on High Level Steps - } - else if (YSize < (yPageSize * SixLinesPerInch / _SevenLinesPerInch)) - { - Console.WriteLine("'PageBreak',6,'Yes','HLS will fit on 1 Page at 7 LPI',{0},{1},{2}, {3}, {4},'{5}'", MyItemInfo.ItemID, YSize, yPageSize, yWithinMargins, (int)(100 * yWithinMargins / yPageSize), MyItemInfo.ShortPath); - return 3; // High Level Step can fit at SevenLinesPerInch - } - else // The entire step cannot fit go ahead and kick to the next page - { - if (yWithinMargins > yPageSize / 2) - { - // If High level Step will not fit, kick to the next page - Console.WriteLine("'PageBreak',3.1,'No','HLS will have to split anyway',{0},{1},{2}, {3}, {4},'{5}'", MyItemInfo.ItemID, YSize, yPageSize, yWithinMargins, (int)(100 * yWithinMargins / yPageSize), MyItemInfo.ShortPath); - if (MyItemInfo.IsHigh) - WalkStepLevel(this,this.YTopMost); - return 0;// Otherwise stay on this page - } - Console.WriteLine("'PageBreak',3.2,'Yes','HLS will have to split',{0},{1},{2}, {3}, {4},'{5}'", MyItemInfo.ItemID, YSize, yPageSize, yWithinMargins, (int)(100 * yWithinMargins / yPageSize), MyItemInfo.ShortPath); - if (MyItemInfo.IsHigh) - WalkStepLevel(this,this.YTopMost); - return 1; // Paginate on High Level Steps - } + //Console.WriteLine("'PageBreak',2,'Yes','HLS will fit on 1 Page',{0},{1},{2}, {3}, {4},'{5}'", MyItemInfo.ItemID, YSize, yPageSize, yWithinMargins, (int)(100 * yWithinMargins / yPageSize), MyItemInfo.ShortPath); + ShowPageBreak(5, "HLS will fit on 1 Page at 6 LPI", "Yes", YSize, yPageSize, yWithinMargins); + return 1; } - if (yWithinMargins > yPageSize / 2) + else if (MyItemInfo.ActiveFormat.MyStepSectionLayoutData.CompressSteps && (YSize + SixLinesPerInch) < (yPageSize * SixLinesPerInch / _SevenLinesPerInch)) { - Console.WriteLine("'PageBreak',4,'No','Not Half way down the page',{0},{1},{2}, {3}, {4},'{5}'", MyItemInfo.ItemID, YSize, yPageSize, yWithinMargins, (int)(100 * yWithinMargins / yPageSize), MyItemInfo.ShortPath); - return 0; // More than half way down the page + //Console.WriteLine("'PageBreak',3,'Yes','HLS will fit on 1 Page at 7 LPI',{0},{1},{2}, {3}, {4},'{5}'", MyItemInfo.ItemID, YSize, yPageSize, yWithinMargins, (int)(100 * yWithinMargins / yPageSize), MyItemInfo.ShortPath); + ShowPageBreak(7, "HLS will fit on 1 Page at 7 LPI", "Yes", YSize, yPageSize, yWithinMargins); + return 3; // High Level Step can fit at SevenLinesPerInch } + else // The entire step cannot fit on a blank page. + { + // if there is more than half a page left, then start to print on the current page + float myFirstPieceSize = GetFirstPieceSize(); //Case 0 + // TODO: Put this line back to case 0, i.e. previous line. This fixes a 16-bit vs 32-bit pagination diff in EO30 Step 20. + //float myFirstPieceSize = GetFirstPieceSize() + 2 * SixLinesPerInch; //Case 10 - this is to match 16bit + if (!ManualPageBreak && MyItemInfo.ActiveFormat.MyStepSectionLayoutData.SpecialPageBreakFlag && yWithinMargins > yPageSize / 2 && + myFirstPieceSize < yWithinMargins ) + { + //Console.WriteLine("'PageBreak',4,'No','HLS will have to split anyway',{0},{1},{2}, {3}, {4},'{5}'", MyItemInfo.ItemID, YSize, yPageSize, yWithinMargins, (int)(100 * yWithinMargins / yPageSize), MyItemInfo.ShortPath); + ShowPageBreak(-4, "HLS will have to split anyway", firstStep , YSize, yPageSize, yWithinMargins); + //BuildPageBreakList(yWithinMargins+SixLinesPerInch,yPageSize-2*SixLinesPerInch); // Determine items where page break(s) occur + BuildPageBreakList(yWithinMargins + SixLinesPerInch, yPageSize); // Case 5 - Determine items where page break(s) occur + return 0; // Stay on this page + } + + // Less than half a page left, start printing on a new page. + //Console.WriteLine("'PageBreak',5,'Yes','HLS will have to split',{0},{1},{2}, {3}, {4},'{5}'", MyItemInfo.ItemID, YSize, yPageSize, yWithinMargins, (int)(100 * yWithinMargins / yPageSize), MyItemInfo.ShortPath); + ShowPageBreak(5, "HLS will have to split", "Yes", YSize, yPageSize, yWithinMargins); + // Determine items where page break(s) occur + //BuildPageBreakList(yPageSize, yPageSize - 2 * SixLinesPerInch); // Case Base + BuildPageBreakList(yPageSize, yPageSize); // Case 1 :Works for ES05 Step 15 SubStep 7 + return 1; // Paginate on High Level Steps + } + //if (yWithinMargins > yPageSize / 2) + //{ + // Console.WriteLine("'PageBreak',4,'No','Not Half way down the page',{0},{1},{2}, {3}, {4},'{5}'", MyItemInfo.ItemID, YSize, yPageSize, yWithinMargins, (int)(100 * yWithinMargins / yPageSize), MyItemInfo.ShortPath); + // return 0; // More than half way down the page + //} //if (ChildrenBelow.Count > 0 && ChildrenBelow[0].YSize < yWithinMargins) // return 0; - Console.WriteLine("'PageBreak',5,'Yes','At least half the page is filled',{0},{1},{2},{3}, {4},'{5}'", MyItemInfo.ItemID, YSize, yPageSize, yWithinMargins, (int)(100 * yWithinMargins / yPageSize), MyItemInfo.ShortPath); - return 2; + //Console.WriteLine("'PageBreak',5,'Yes','At least half the page is filled',{0},{1},{2},{3}, {4},'{5}'", MyItemInfo.ItemID, YSize, yPageSize, yWithinMargins, (int)(100 * yWithinMargins / yPageSize), MyItemInfo.ShortPath); + //return 2; + throw new Exception("PageBreak Logic Missing, vlnParagraph.cs"); + } + /// + /// This gets the height of the step with it's Caution's, Notes and potentially any First Substeps + /// + /// + private float GetFirstPieceSize() + { + vlnParagraph paraLast = GetFirstPieceLastPart(); + float retval = (paraLast.YBottom) - YTopMost; + //Console.WriteLine(MyItemInfo.DBSequence); + return retval; + } + public override float YBottom + { + get + { + float bottom = YOffset + Height; + if (PartsBelow != null) + { + foreach (vlnPrintObject part in PartsBelow) + { + float partBottom = part.YBottom; + bottom = Math.Max(partBottom, bottom); + } + } + return bottom; + } + } + private vlnParagraph GetFirstPieceLastPart() + { + vlnParagraph para = this; + if (!MyItemInfo.ActiveFormat.MyStepSectionLayoutData.PaginateOnFirstSubstep && ChildrenBelow != null && ChildrenBelow.Count > 0) + { + para = ChildrenBelow[0].GetFirstPieceLastPart(); + } + if (ChildrenRight != null && ChildrenRight.Count > 0) + { + foreach(vlnParagraph paraRight in ChildrenRight) + { + vlnParagraph paraRightLast = paraRight.GetFirstPieceLastPart(); + if (paraRightLast.YBottom > para.YBottom) + para = paraRightLast; + } + } + return para; + } + private void ShowPageBreak(int instance, string message, string breakOrNot, float YSize, float yPageSize, float yWithinMargins) + { + if (breakOrNot == "Yes") + Console.WriteLine("{0}", MyItemInfo.DBSequence); //,instance); + // Console.WriteLine("{0},{1}", MyItemInfo.DBSequence, IsFirstSubStep(MyItemInfo)); //,instance); + // Console.WriteLine("{0},'{1}','{2}',{3},{4},{5},{6},{7},'{8}'", instance, message, breakOrNot, + // MyItemInfo.ItemID, YSize, yPageSize, yWithinMargins, (int)(100 * yWithinMargins / yPageSize), MyItemInfo.DBSequence); + } + private void BuildPageBreakList(float ySpaceOnCurPage, float yPageSize) + { + ParagraphLocations myLocations = new ParagraphLocations(); + BuildLocationList(YTopMost, myLocations); + StepLevelList myList = myLocations.BuildStepLevelList(); + // Find Break Locations in the list based upon StepLevel and yLocation + float yTop = 0; + float yLowerLimit = (yPageSize - 2 * SixLinesPerInch) / 2; + float yStart = Math.Max(0,(yPageSize - 2 * SixLinesPerInch) - ySpaceOnCurPage); + //Console.WriteLine("'yStart',{0},{1}", MyItemInfo.DBSequence, yStart); + + // The following three lines make page breaking match 16-bit: + //yLowerLimit = yStart - SixLinesPerInch + ySpaceOnCurPage / 2; + //if ((yStart + MyItemInfo.MyDocStyle.Layout.TopRow + 2 * SixLinesPerInch)>((MyItemInfo.MyDocStyle.Layout.TopRow+yPageSize-2*SixLinesPerInch)/2)) + // yLowerLimit = yStart + 2 * SixLinesPerInch; + + // Make sure that the FirstPiece (Caution Note HLS and First Substeps) fit + float myFirstPieceSize = GetFirstPieceSize(); //Case 0 + if (myFirstPieceSize < ySpaceOnCurPage) yLowerLimit = Math.Max(myFirstPieceSize + yStart, yLowerLimit); + while ((YSize - yTop) >= ySpaceOnCurPage) + { + vlnParagraph paraBreak = FindPageBreak(yStart, ySpaceOnCurPage, yLowerLimit, myList); + // yTopNew is y Location of this page break. YTopMost is top of HLS, including any Cautions/Notes/Boxes/etc + float yTopNew = paraBreak.YVeryTop - YTopMost; + RemoveProcessedParagraphs(myList, yTopNew-yTop); + yTop = yTopNew; + MyPageHelper.ParaBreaks.Add(paraBreak); + ySpaceOnCurPage = yPageSize - 2 * SixLinesPerInch; // Allow for continue message and blank line. + yLowerLimit = ySpaceOnCurPage / 2; + yStart = 0; + } + } + /// + /// Find items from previous page (yLocation less than yTop) and remove them from the list. + /// yTop is the new starting location on the next page for this step. + /// + /// + /// + private void RemoveProcessedParagraphs(StepLevelList myList, float yTop) + { + // the two CleanUpLists are used to remove items from + // the original list because list items cannot be removed in a + // 'foreach'. + List CleanupListStepLevel = new List(); + foreach(int stepLevel in myList.Keys) + { + List CleanupListYLocation = new List(); + SortedList AdjustYLocation = new SortedList(); + foreach (float yLocation in myList[stepLevel].Keys) + { + if (-yLocation <= yTop) + CleanupListYLocation.Add(yLocation); + else + AdjustYLocation.Add(-yLocation, yLocation); // order in ascending order + } + //if (stepLevel == 3) Console.WriteLine("here"); + foreach (float yLocation in CleanupListYLocation) + myList[stepLevel].Remove(yLocation); + foreach (float yLocation in AdjustYLocation.Keys) + { + vlnParagraph para = myList[stepLevel][-yLocation]; + myList[stepLevel].Remove(-yLocation); + // shift yLocation by yTop to work with items whose locations + // are defined from the top of the new page rather than + // from the beginning of the step. + // Note that yLocation is negative to have items in descending + // order so that adding yTop decrements their values. + myList[stepLevel].Add(yTop-yLocation, para); + } + if (myList[stepLevel].Count == 0) + CleanupListStepLevel.Add(stepLevel); + } + foreach (int stepLevel in CleanupListStepLevel) + myList.Remove(stepLevel); + } + /// + /// Finds the highest StepLevel (lowest StepLevel number, 0 = HLS, 1 = first substep) that + /// fills the page sufficiently (more than half-full) + /// + /// + /// + /// + /// + private static vlnParagraph FindPageBreak(float yStart, float yUpperLimit, float yLowerLimit, StepLevelList myList) + { + foreach (int stepLevel in myList.Keys) // loop thru StepLevels, starting with lowest. + { + foreach (float yLocation in myList[stepLevel].Keys) // loop thru yLocation + { + // The top of this step will fit onto page (-yLocation < yWithinMargins) + if (-yLocation < yUpperLimit) + //if (-yLocation < yWithinMargins && myList[stepLevel][yLocation].MyItemInfo.MyPrevious != null) + { + //ItemInfo prev = myList[stepLevel][yLocation].MyItemInfo.MyPrevious; + //if (myList[stepLevel][yLocation].MyItemInfo.ItemID == 5609) Console.WriteLine("aer"); + //if (myList[stepLevel][yLocation].MyItemInfo.ItemID == 5613) Console.WriteLine("rno"); + // The top of this step is more than 1/2 way down the page + if ((-yLocation + yStart) >= yLowerLimit) + { + return myList[stepLevel][yLocation]; + } + // if is a caution or note & parent is a substep and entire substep doesn't fit, break. + if ((myList[stepLevel][yLocation].MyItemInfo.IsNote || myList[stepLevel][yLocation].MyItemInfo.IsCaution) && + !myList[stepLevel][yLocation].MyParent.MyItemInfo.IsHigh && + myList[stepLevel][yLocation].MyParent.YSize > (yUpperLimit + yLocation)) + { + return myList[stepLevel][yLocation]; + } + } + } + } + return null; + } + /// + /// Builds a list of paragraphs by StepLevel and yLocation in descending order. + /// + /// + /// + private void BuildLocationList(float yTopMost, ParagraphLocations myLocations) + { + foreach (vlnParagraph child in ChildrenAbove) + child.BuildLocationList(yTopMost, myLocations); + foreach (vlnParagraph child in ChildrenLeft) + child.BuildLocationList(yTopMost, myLocations); + + // Add a list entry consisting of StepLevel, yoffset from the beginning of this step, paragraph itself + myLocations.Add(this, yTopMost); + + foreach (vlnParagraph child in ChildrenRight) + child.BuildLocationList(yTopMost, myLocations); + foreach (vlnParagraph child in ChildrenBelow) + child.BuildLocationList(yTopMost, myLocations); } private int COL_WID_ADJ = 6; // adjusts for incorrect use of WidSTable when breaking a line (it breaks 6 chars too short) public vlnParagraph(vlnParagraph parent, PdfContentByte cb, ItemInfo itemInfo, float xoff, float yoff, int rnoLevel, int maxRNO, FormatInfo formatInfo) @@ -459,7 +683,7 @@ namespace Volian.Print.Library } } float yOffRight = yoff; - float RnoOffset = ToInt(formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.ColRTable, maxRNO); + float RnoOffset = ToInt(formatInfo.MyStepSectionLayoutData.ColRTable, maxRNO); if (rnoLevel < maxRNO && itemInfo.RNOs != null) yOffRight = ChildrenRight.Add(cb, itemInfo.RNOs, XOffset + RnoOffset, YTop, YTop, rnoLevel + 1, maxRNO, formatInfo); // Need code to determine if the table will overlap the Right Column if it does then // use YOffRight rather than yoff @@ -470,7 +694,7 @@ namespace Volian.Print.Library if (rnoLevel >= maxRNO && itemInfo.RNOs != null) yoff = ChildrenBelow.Add(cb, itemInfo.RNOs, XOffset, yoff, yoff, rnoLevel + 1, maxRNO, formatInfo); yoff = Math.Max(yoff, yOffRight); // TODO - use RNOSepAfterAER flag too: - string tmpRnoSepStr = formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionPrintData.RNOSepString; + string tmpRnoSepStr = formatInfo.MyStepSectionPrintData.RNOSepString; if (rnoLevel < maxRNO && itemInfo.RNOs != null && tmpRnoSepStr != null) { float xsep = MyHighLevelParagraph.XOffset + RnoOffset; @@ -492,7 +716,7 @@ namespace Volian.Print.Library if (!aerFigure) { // adjust for RNO - int colR = int.Parse(formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.ColRTable.Split(",".ToCharArray())[itemInfo.ColumnMode]); + int colR = int.Parse(formatInfo.MyStepSectionLayoutData.ColRTable.Split(",".ToCharArray())[itemInfo.ColumnMode]); XOffset += (colR * maxRNO) / 2; XOffset -= (hls1.XOffset - (float)itemInfo.MyDocStyle.Layout.LeftMargin) / 2; } @@ -537,8 +761,8 @@ namespace Volian.Print.Library // else // ChangeBarLocation() ChangeBarData cbd = formatInfo.PlantFormat.FormatData.ProcData.ChangeBarData; - int cols = formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.ColS ?? 0; - int colr = ToInt(formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.ColRTable, maxRNO); + int cols = formatInfo.MyStepSectionLayoutData.ColS ?? 0; + int colr = ToInt(formatInfo.MyStepSectionLayoutData.ColRTable, maxRNO); float col = (cbd.AbsoluteFixedChangeColumn) ? ((cbd.FixedAERChangeColumn ?? 0) > 0) ? (xoff > (cols + colr + COL_WID_ADJ)) ? @@ -574,8 +798,8 @@ namespace Volian.Print.Library private int ChangeBarLocation(float c, vlnParagraph paragraph, FormatInfo formatInfo, int maxRNO) { int fixedChgCol = formatInfo.PlantFormat.FormatData.ProcData.ChangeBarData.FixedChangeColumn ?? 0; - int cols = formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.ColS ?? 0; - int colr = ToInt(formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.ColRTable, maxRNO); + int cols = formatInfo.MyStepSectionLayoutData.ColS ?? 0; + int colr = ToInt(formatInfo.MyStepSectionLayoutData.ColRTable, maxRNO); if (fixedChgCol < -10 || fixedChgCol >= 0) return ((fixedChgCol > 0) ? fixedChgCol : (fixedChgCol == 0) ? (int)c + 1 : @@ -650,10 +874,10 @@ namespace Volian.Print.Library xoff += (float)((bx.TxtStart + XOffsetBox + (bx.TxtWidth / 2)) - (hdrWidth / 2)); // xoff starts as left margin } } - else if (formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.Separator.Location > 0) + else if (formatInfo.MyStepSectionLayoutData.Separator.Location > 0) { // if there is a separator location, use it - 16bit code used the separator location as a divisor: - xoff = XOffset + AdjustToCharPosition((float)((para.Width - hdrWidth) / formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.Separator.Location)); + xoff = XOffset + AdjustToCharPosition((float)((para.Width - hdrWidth) / formatInfo.MyStepSectionLayoutData.Separator.Location)); } else xoff = XOffset + (para.Width / 2) + (hdrWidth / 2); // XOffset has left margin included @@ -707,7 +931,8 @@ namespace Volian.Print.Library set { vlnParagraph vp = this as vlnParagraph; - if (vp != null && vp.MyItemInfo != null && vp.MyItemInfo.ItemID == 55) Console.WriteLine("here"); + //if (vp != null && vp.MyItemInfo != null && vp.MyItemInfo.ItemID == 55) + // Console.WriteLine("here"); _YTop = value; } @@ -861,7 +1086,7 @@ namespace Volian.Print.Library } else if (itemInfo.IsHigh) { - Width = _WidthAdjust + ToInt(formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.WidSTablePrint, maxRNO); + Width = _WidthAdjust + ToInt(formatInfo.MyStepSectionLayoutData.WidSTablePrint, maxRNO); } else if (MyParent == null) { @@ -883,5 +1108,136 @@ namespace Volian.Print.Library } } + /// + /// First order by stepLevel, then within a stepLevel, order by descending yLocation on page. + /// Want to find maximum y value that fits on page, i.e. put the most on page that can + /// fit which is defined by the largest yLocation + /// + public class StepLevelList : SortedDictionary> + { + public StepLevelList() : base() + { + } + public void Add(int stepLevel, float yLocation, vlnParagraph para) + { + if (stepLevel == 0) return; + if (!this.ContainsKey(stepLevel)) + this.Add(stepLevel, new SortedDictionary()); + // using a negative for yLocation so that its in descending order: + if (!this[stepLevel].ContainsKey(-yLocation)) + this[stepLevel].Add(-yLocation, para); + } + } + public class ParagraphLocations : List + { + public ParagraphLocations() + : base() + { + } + public void Add(vlnParagraph myParagraph, float yTopMost) + { + ParagraphLocation foundOverlap = FindOverlap(myParagraph); + if (foundOverlap == null) + { + this.Add(new ParagraphLocation(yTopMost,myParagraph)); + return; + } + ParagraphLocation doubleOverlap = FindOverlap(foundOverlap); + while (doubleOverlap != null) + { + doubleOverlap.Merge(foundOverlap); + this.Remove(foundOverlap); + foundOverlap = doubleOverlap; + doubleOverlap = FindOverlap(foundOverlap); + } + } + private ParagraphLocation FindOverlap(vlnParagraph myParagraph) + { + foreach (ParagraphLocation paraLoc in this) + if (paraLoc.Overlap(myParagraph)) + return paraLoc; + return null; + } + private ParagraphLocation FindOverlap(ParagraphLocation myParaLoc) + { + foreach (ParagraphLocation paraLoc in this) + if (paraLoc != myParaLoc && paraLoc.Overlap(myParaLoc)) + return paraLoc; + return null; + } + internal StepLevelList BuildStepLevelList() + { + StepLevelList myList = new StepLevelList(); + foreach (ParagraphLocation paraLoc in this) + myList.Add(paraLoc.StepLevel, paraLoc.YTop, paraLoc.MyParagraph); + return myList; + } + } + public class ParagraphLocation + { + private float _YTop; + public float YTop + { + get { return _YTop; } + set { _YTop = value; } + } + private float _YBottom; + public float YBottom + { + get { return _YBottom; } + set { _YBottom = value; } + } + private int _StepLevel; + public int StepLevel + { + get { return _StepLevel; } + set { _StepLevel = value; } + } + private vlnParagraph _MyParagraph; + public vlnParagraph MyParagraph + { + get { return _MyParagraph; } + set { _MyParagraph = value; } + } + public ParagraphLocation(float yTopMost,vlnParagraph myParagraph) + { + MyParagraph =myParagraph; + YTop = myParagraph.YVeryTop - yTopMost; + YBottom = myParagraph.YBottom - yTopMost; + StepLevel = myParagraph.MyItemInfo.StepLevel; + } + public bool Overlap(vlnParagraph otherParagraph) + { + if (Between(otherParagraph.YTop, YTop, YBottom)) return true; + if (Between(otherParagraph.YBottom, YTop, YBottom)) return true; + if(Between(YTop,otherParagraph.YVeryTop,otherParagraph.YBottom)) return true; + if(Between(YBottom,otherParagraph.YVeryTop,otherParagraph.YBottom)) return true; + return false; + } + public static bool Between(float x, float lower, float higher) + { return x >= lower && x <= higher; } + public bool Overlap(ParagraphLocation otherParagraphLocation) + { + if (Between(otherParagraphLocation.YTop, YTop, YBottom)) return true; // The top is within the other + if (Between(otherParagraphLocation.YBottom, YTop, YBottom)) return true; // The bottom is within the other + if(Between(YTop,otherParagraphLocation.YTop,otherParagraphLocation.YBottom)) return true; // the other top is within this one + if(Between(YBottom,otherParagraphLocation.YTop,otherParagraphLocation.YBottom)) return true;// I believe this is unnecessary + return false; + } + public void Merge(vlnParagraph otherParagraph) + { + if (StepLevel < otherParagraph.MyItemInfo.StepLevel) MyParagraph = otherParagraph; + YTop = Math.Min(YTop, otherParagraph.YVeryTop); + YBottom = Math.Max(YBottom, otherParagraph.YBottom); + StepLevel = Math.Max(StepLevel, otherParagraph.MyItemInfo.StepLevel); + } + public void Merge(ParagraphLocation otherParagraphLocation) + { + if (StepLevel < otherParagraphLocation.StepLevel) MyParagraph = otherParagraphLocation.MyParagraph; + YTop = Math.Min(YTop, otherParagraphLocation.YTop); + YBottom = Math.Max(YBottom, otherParagraphLocation.YBottom); + StepLevel = Math.Max(StepLevel, otherParagraphLocation.StepLevel); + } + } }