Ejemplo n.º 1
0
        // Place a rectangle in the current column. Caller must ensure that it fits!
        private void PlaceInCurrentColumn(IPrintableRectangle rectangle, int startLine, int countLines)
        {
            countLines = Math.Min(countLines, rectangle.Boxes.Height - startLine);      // if countLines is too big, reduce it.
#if DEBUG
            // Make sure it fits.
            int  numberLinesFit;
            bool fits = FitsInCurrentColumn(rectangle, startLine, out numberLinesFit);
            Debug.Assert(fits || countLines <= numberLinesFit);
#endif //DEBUG

            // Add the description to the list of positioned rectangles.
            PositionedRectangle positionedRectangle;
            positionedRectangle.description = rectangle;
            positionedRectangle.pageNumber  = currentPage;
            positionedRectangle.location    = new PointF(currentX, currentY);
            positionedRectangle.startLine   = startLine;
            positionedRectangle.countLines  = countLines;
            positions.Add(positionedRectangle);

            // Update the variables.
            if (CurrentColumnEmpty)
            {
                columnWidth = rectangle.Boxes.Width * boxSize;
            }
            currentY += countLines * boxSize + spacing;
            if (currentY >= pageSize.Height)
            {
                StartNewColumn();
            }
        }
Ejemplo n.º 2
0
        // Layout a single description as many times as you can in one page. Return the number of descriptions
        // laid out. If the description is too large for one page, 1 is returned and the description is laid out on multiple
        // pages, so be sure to check PageCount anyway.
        public int LayoutOneDescriptionPage(IPrintableRectangle rectangle)
        {
            int countRectangles = 0;
            int startLine = 0, countLines;

            if (!PageSizeBigEnough(new IPrintableRectangle[] { rectangle }))
            {
                throw new ApplicationException(MiscText.PageTooSmall);
            }

            StartNewPage();
            int startPage = currentPage;

            // Loop until we go the next page. Finish off a description that's in progress.
            while (currentPage == startPage || startLine != 0)
            {
                if (FitsInCurrentColumn(rectangle, startLine, out countLines))
                {
                    PlaceInCurrentColumn(rectangle, startLine, countLines);
                    startLine        = 0;
                    countRectangles += 1;
                }
                else
                {
                    // It doesn't fit in the current column.
                    if (CurrentColumnEmpty)
                    {
                        if (countLines == 0)
                        {
                            // the description is too wide for the remaining area.
                            StartNewPage();
                        }
                        else
                        {
                            // The description is too large for one column. Put as much as will fit in one column.
                            PlaceInCurrentColumn(rectangle, startLine, countLines);
                            startLine += countLines;
                        }
                    }
                    else
                    {
                        // The description won't fit in the rest of this column. Start a new one.
                        StartNewColumn();
                    }
                }
            }

            // If the current page isn't empty and we placed more than one description, remove the last description,
            // because it shouldn't have been placed.
            if (!CurrentPageEmpty && countRectangles > 1)
            {
                RemoveLastRectangle();
                --countRectangles;
            }

            return(countRectangles);
        }
Ejemplo n.º 3
0
        // Determine if the given rectangle (starting at a given line) would fully fit in the current column.
        // Also returns the number of lines that would fit.
        private bool FitsInCurrentColumn(IPrintableRectangle rectangle, int startLine, out int numberLinesFit)
        {
            numberLinesFit = 0;
            Size  sizeInBoxes = rectangle.Boxes;
            SizeF size        = new SizeF(sizeInBoxes.Width * boxSize, (sizeInBoxes.Height - startLine) * boxSize);

            // Will width fit?
            if (CurrentColumnEmpty)
            {
                // A column has not been started. Check that width the description <= remaining space on page.
                if (size.Width > pageSize.Width - currentX)
                {
                    return(false);
                }
            }
            else
            {
                // A column has been started. Check that the width of this description is <= column width
                if (size.Width > columnWidth)
                {
                    return(false);
                }
            }

            // Will height fit?
            float remainingHeight = pageSize.Height - currentY;

            if (size.Height <= remainingHeight)
            {
                // fully fits
                numberLinesFit = rectangle.Boxes.Height;
                return(true);
            }
            else
            {
                // doesn't fully fit. How much does fit?
                numberLinesFit = (int)(remainingHeight / boxSize);
                return(false);
            }
        }
Ejemplo n.º 4
0
        // Place a rectangle in the current column. Caller must ensure that it fits!
        private void PlaceInCurrentColumn(IPrintableRectangle rectangle, int startLine, int countLines)
        {
            countLines = Math.Min(countLines, rectangle.Boxes.Height - startLine);      // if countLines is too big, reduce it.
            #if DEBUG
            // Make sure it fits.
            int numberLinesFit;
            bool fits = FitsInCurrentColumn(rectangle, startLine, out numberLinesFit);
            Debug.Assert(fits || countLines <= numberLinesFit);
            #endif //DEBUG

            // Add the description to the list of positioned rectangles.
            PositionedRectangle positionedRectangle;
            positionedRectangle.description = rectangle;
            positionedRectangle.pageNumber = currentPage;
            positionedRectangle.location = new PointF(currentX, currentY);
            positionedRectangle.startLine = startLine;
            positionedRectangle.countLines = countLines;
            positions.Add(positionedRectangle);

            // Update the variables.
            if (CurrentColumnEmpty) {
                columnWidth = rectangle.Boxes.Width * boxSize;
            }
            currentY += countLines * boxSize + spacing;
            if (currentY >= pageSize.Height)
                StartNewColumn();
        }
Ejemplo n.º 5
0
        // Check if page size is big enough to hold any descriptions at all. If not, throw exception.
        private bool PageSizeBigEnough(IPrintableRectangle[] rectangles)
        {
            if (pageSize.Width < boxSize || pageSize.Height < boxSize)
                return false;

            foreach (IPrintableRectangle desc in rectangles) {
                if (desc.Boxes.Width * boxSize > pageSize.Width)
                    return false;
            }

            return true;
        }
Ejemplo n.º 6
0
        // Determine if the given rectangle (starting at a given line) would fully fit in the current column.
        // Also returns the number of lines that would fit.
        private bool FitsInCurrentColumn(IPrintableRectangle rectangle, int startLine, out int numberLinesFit)
        {
            numberLinesFit = 0;
            Size sizeInBoxes = rectangle.Boxes;
            SizeF size = new SizeF(sizeInBoxes.Width * boxSize, (sizeInBoxes.Height - startLine) * boxSize);

            // Will width fit?
            if (CurrentColumnEmpty) {
                // A column has not been started. Check that width the description <= remaining space on page.
                if (size.Width > pageSize.Width - currentX)
                    return false;
            }
            else {
                // A column has been started. Check that the width of this description is <= column width
                if (size.Width > columnWidth)
                    return false;
            }

            // Will height fit?
            float remainingHeight = pageSize.Height - currentY;
            if (size.Height <= remainingHeight) {
                // fully fits
                numberLinesFit = rectangle.Boxes.Height;
                return true;
            }
            else {
                // doesn't fully fit. How much does fit?
                numberLinesFit = (int) (remainingHeight / boxSize);
                return false;
            }
        }
Ejemplo n.º 7
0
        // Layout a single description as many times as you can in one page. Return the number of descriptions
        // laid out. If the description is too large for one page, 1 is returned and the description is laid out on multiple
        // pages, so be sure to check PageCount anyway.
        public int LayoutOneDescriptionPage(IPrintableRectangle rectangle)
        {
            int countRectangles = 0;
            int startLine = 0, countLines;

            if (!PageSizeBigEnough(new IPrintableRectangle[] { rectangle }))
                throw new ApplicationException(MiscText.PageTooSmall);

            StartNewPage();
            int startPage = currentPage;

            // Loop until we go the next page. Finish off a description that's in progress.
            while (currentPage == startPage || startLine != 0) {
                if (FitsInCurrentColumn(rectangle, startLine, out countLines)) {
                    PlaceInCurrentColumn(rectangle, startLine, countLines);
                    startLine = 0;
                    countRectangles += 1;
                }
                else {
                    // It doesn't fit in the current column.
                    if (CurrentColumnEmpty) {
                        if (countLines == 0) {
                            // the description is too wide for the remaining area.
                            StartNewPage();
                        }
                        else {
                            // The description is too large for one column. Put as much as will fit in one column.
                            PlaceInCurrentColumn(rectangle, startLine, countLines);
                            startLine += countLines;
                        }
                    }
                    else {
                        // The description won't fit in the rest of this column. Start a new one.
                        StartNewColumn();
                    }
                }
            }

            // If the current page isn't empty and we placed more than one description, remove the last description,
            // because it shouldn't have been placed.
            if (! CurrentPageEmpty && countRectangles > 1) {
                RemoveLastRectangle();
                --countRectangles;
            }

            return countRectangles;
        }
Ejemplo n.º 8
0
        // Layout one copy of each of multiple descriptions on one or more pages.
        public void LayoutMultipleDescriptions(IPrintableRectangle[] rectangles)
        {
            int startLine = 0, countLines;

            if (rectangles.Length == 0)
                return;

            if (!PageSizeBigEnough(rectangles))
                throw new ApplicationException(MiscText.PageTooSmall);

            List<IPrintableRectangle> rectList = new List<IPrintableRectangle>(rectangles);

            // Sort by largest width first, then by largest height.
            rectList.Sort(delegate(IPrintableRectangle d1, IPrintableRectangle d2) {
                Size size1 = d1.Boxes, size2 = d2.Boxes;
                if (size1.Width < size2.Width)
                    return 1;
                else if (size1.Width > size2.Width)
                    return -1;
                else if (size2.Height != size1.Height)
                    return size2.Height.CompareTo(size1.Height);
                else
                    return Array.IndexOf(rectangles, d1) - Array.IndexOf(rectangles, d2);
            });

            StartNewPage();

            // At each step, we place the largest one that will fit. At a column start, we
            // place the largest one, period.
            while (rectList.Count > 0) {
                // Select a description to place.
                IPrintableRectangle rectToPlace;
                if (CurrentColumnEmpty)
                    rectToPlace = rectList[0];
                else {
                    rectToPlace = null;
                    foreach (IPrintableRectangle rect in rectList) {
                        if (FitsInCurrentColumn(rect, 0, out countLines)) {
                            rectToPlace = rect;
                            break;
                        }
                    }
                    if (rectToPlace == null) {
                        // Nothing fits. Start a new column.
                        StartNewColumn();
                        continue;
                    }
                }

                // Remove it from the list so we only place it once.
                rectList.Remove(rectToPlace);

                // Place it, in multiple pieces if needed.
                startLine = 0;
                while (!FitsInCurrentColumn(rectToPlace, startLine, out countLines)) {
                    if (countLines == 0)
                        StartNewPage();
                    else {
                        PlaceInCurrentColumn(rectToPlace, startLine, countLines);
                        startLine += countLines;
                    }
                }
                PlaceInCurrentColumn(rectToPlace, startLine, countLines);
            }
        }