LayoutResult ILayoutManager.Measure(LayoutContext context)
        {
            var content = (CalendarContentRange)context.ContentRange;

            LayoutResult result;

            using (var calendarData = new CalendarData(_calendar))
            {
                // the first time run
                if (content == null)
                {
                    content = new CalendarContentRange(_calendar, calendarData.GetFirstMonth(), calendarData.GetLastMonth());
                }
                else if ((context.LayoutDirection & LayoutDirection.Vertical) != 0)                 // continue vertical run
                {
                    // do we have anything else to render ?
                    if (!calendarData.HasMonthAfter(content.MonthTo))
                    {
                        return(new LayoutResult(null, LayoutStatus.NoContent | LayoutStatus.Complete, new SizeF()));
                    }

                    var continuedRange = content.StaticContentRange.ContinueRange(context);
                    content = new CalendarContentRange(continuedRange, _calendar, calendarData.GetNextMonth(content.MonthTo), calendarData.GetLastMonth());
                }
                else if ((context.LayoutDirection & LayoutDirection.Horizontal) != 0)                 // continue horizontal run
                {
                    var continuedRange = content.StaticContentRange.ContinueRange(context);
                    content = new CalendarContentRange(continuedRange, _calendar, content.MonthFrom, content.MonthTo);
                }

                result = MeasureContentRange(content, calendarData, context.AvailableSize);
            }

            return(result);
        }
        private LayoutResult MeasureContentRange(CalendarContentRange content, CalendarData calendarData, SizeF maxSize)
        {
            SizeF        actualSize   = new SizeF();
            LayoutStatus layoutStatus = LayoutStatus.None;

            MonthInfo currentMonth     = content.MonthFrom;
            MonthInfo lastMonthtFitted = currentMonth;

            while (currentMonth <= content.MonthTo)
            {
                // measure the month
                SizeF monthSize = calendarData.MeasureMonth(
                    currentMonth,
                    new SizeF(_calendar.Width.ToTwips(), _calendar.Height.ToTwips()));

                if (currentMonth != content.MonthFrom)
                {
                    monthSize.Height += CalendarData.MonthsSpace;
                }

                if (actualSize.Height + monthSize.Height > maxSize.Height)
                {
                    layoutStatus |= LayoutStatus.ContinueVertically;
                    _continueVerticallyAttempts++;
                }

                // if the current month didn't fit vertically
                bool continueVertically = (layoutStatus & LayoutStatus.ContinueVertically) == LayoutStatus.ContinueVertically;
                // limit the number of attempts vertical continue
                // currentMonth.Month != lastMonthtFitted.Month for prevent the creation of blank pages (case 149145)
                if (continueVertically && _continueVerticallyAttempts < 2 && currentMonth.Month != lastMonthtFitted.Month)
                {
                    break;
                }

                layoutStatus      |= LayoutStatus.SomeContent;
                actualSize.Width   = Math.Max(actualSize.Width, monthSize.Width);
                actualSize.Height += monthSize.Height;

                // if the current month didn't fit vertically AND emptyFplPage == true
                if (continueVertically)
                {
                    break;
                }

                lastMonthtFitted = currentMonth;
                if (!calendarData.HasMonthAfter(currentMonth))
                {
                    // all months were fitted
                    layoutStatus |= LayoutStatus.Complete;
                    break;
                }

                currentMonth = calendarData.GetNextMonth(currentMonth);
            }

            if (actualSize.Width > maxSize.Width)
            {
                layoutStatus |= LayoutStatus.ContinueHorizontally;
            }

            return(new LayoutResult(
                       new CalendarContentRange(content.StaticContentRange, _calendar, content.MonthFrom, lastMonthtFitted),
                       layoutStatus, actualSize));
        }