Exemplo n.º 1
0
 /// <summary>
 /// Create a Spreadsheet Cell.
 /// </summary>
 /// <param name="spreadsheetRow">The spreadsheet row associated with this cell.</param>
 /// <param name="spreadsheetColumn">The spreadsheet column associated with this cell.</param>
 public SpreadsheetCell(SpreadsheetRow spreadsheetRow, SpreadsheetColumn spreadsheetColumn)
 {
     // Initialize the Object.
     this.spreadsheetRow    = spreadsheetRow;
     this.spreadsheetColumn = spreadsheetColumn;
     this.style             = spreadsheetColumn.Style;
     this.IsModified        = true;
 }
Exemplo n.º 2
0
 public AnimatedCell(SpreadsheetColumn spreadsheetColumn, SpreadsheetRow spreadsheetRow, Style[] animationArray)
 {
     // Initialize the object. Note that the first color in the sequence was set when the change in value was discovered, so
     // the sequencing actually begins with the second style in the sequence of colors.
     this.AnimationIndex    = 1;
     this.AnimationArray    = animationArray;
     this.SpreadsheetColumn = spreadsheetColumn;
     this.SpreadsheetRow    = spreadsheetRow;
 }
Exemplo n.º 3
0
        /// <summary>
        /// Compares an AnimatedCell address to another object.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public int CompareTo(object obj)
        {
            // Compare this against another AnimatedCell.
            if (obj is AnimatedCell)
            {
                AnimatedCell operand = (AnimatedCell)obj;

                // The rows are compared by testing the primary key elements of each row.
                foreach (DataColumn dataColumn in this.SpreadsheetRow.Table.PrimaryKey)
                {
                    int comparison = this.SpreadsheetRow[dataColumn].CompareTo(operand.SpreadsheetRow[dataColumn]);
                    if (comparison != 0)
                    {
                        return(comparison);
                    }
                }

                // If the two rows are the same, compare the column.
                return(this.SpreadsheetColumn.Ordinal.CompareTo(operand.SpreadsheetColumn.Ordinal));
            }

            // Compare this object against the column and row addresses.
            if (obj is object[])
            {
                // Extract the row and column from the arguments.
                SpreadsheetColumn spreadsheetColumn = (SpreadsheetColumn)((object[])obj)[0];
                SpreadsheetRow    spreadsheetRow    = (SpreadsheetRow)((object[])obj)[1];

                // The rows are compared by testing the primary key elements of each row.
                foreach (DataColumn dataColumn in this.SpreadsheetRow.Table.PrimaryKey)
                {
                    int comparison = this.SpreadsheetRow[dataColumn].CompareTo(spreadsheetRow[dataColumn]);
                    if (comparison != 0)
                    {
                        return(comparison);
                    }
                }

                // If the two rows are the same, compare the column.
                return(this.SpreadsheetColumn.Ordinal.CompareTo(spreadsheetColumn.Ordinal));
            }

            // Any other comparison isn't supported.
            throw new Exception(string.Format("Can't compare {0} to type {1}", obj.GetType().ToString(),
                                              this.GetType().ToString()));
        }
Exemplo n.º 4
0
        /// <summary>
        /// Measures the document, row and cell dimensions.
        /// </summary>
        /// <returns>A region of the document that has changed.</returns>
        internal Region MeasureData()
        {
            // This area will collect all the rectangles that need to be updated in the viewer.
            Region region = new Region();

            region.MakeEmpty();

            // This is used to collect smaller row and cell rectangles into the largest possible area.  The idea is to minimzed the
            // number of rectangles that the GDI has to handle when the document is redrawn.  Of course, this could be done with an
            // infinite region, but the idea is also to minimize the amount of drawing that needs to be done.
            Rectangle aggregateRectangle = Rectangle.Empty;

            // This is used as a relatively static area where the dimensions of a row in the current view are calcualted.
            Rectangle rowRectangle = Rectangle.Empty;

            // These provide cursors for keeping track of the location as the document is measured.
            Point displayCursor = Point.Empty;
            Point printerCursor = Point.Empty;

            // Initialize the total area of the screen and printed document.  The width of the documents has been calculated by
            // this point (it is calculated in 'MeasureHeader', but the length has not yet been calculated.
            this.displayRectangle = new Rectangle(0, 0, this.headerRectangle.Width, 0);

            // The default view defines which rows are visible and in what order the appear.  It defines the 'visible' document.
            // This code will run through the visible document and assign coordinates to the rows and cells according to their
            // place in the view.
            int rowIndex = 0;

            foreach (DataRowView dataRowView in this.spreadsheetRowView)
            {
                // The underlying row will be updated with coordinates that represent its location in the view.
                SpreadsheetRow spreadsheetRow = (SpreadsheetRow)dataRowView.Row;

                // This index gives the row position within the sorted and filtered view.
                spreadsheetRow.RowViewIndex = rowIndex++;

                // This define the coordinates of this row in the view.
                rowRectangle.X      = displayCursor.X;
                rowRectangle.Y      = displayCursor.Y;
                rowRectangle.Width  = this.displayRectangle.Width;
                rowRectangle.Height = spreadsheetRow.rectangle.Height;

                // The code below will check the coordinates of the rows and cells with the goal of preserving the data that hasn't
                // changed.  However, if the row is invalid, there's no need to add the cells to the update region.  If every cell
                // of every row were entered into the region, it would choke the GDI.  If the row is out of place, this flag will
                // skip the cell checking logic.
                bool isRowValid = true;

                // If the position and height of the row don't agree with where it should be in the DataView, then the coordinates
                // will have to be updated and the row will be added to the list of things that need redrawing.
                if (spreadsheetRow.rectangle.Location != rowRectangle.Location ||
                    spreadsheetRow.rectangle.Height != rowRectangle.Height || !spreadsheetRow.IsVisible)
                {
                    // The entire row will be added to the update region, there's no need to add the cell rectangles as well.
                    // This is done as an optimization; if ever cell in a large document were modified at once, it would blow out
                    // the storage are for a region.
                    isRowValid = false;

                    // Update the coordinates of the row with the calculated rectangle from the view.
                    spreadsheetRow.rectangle = rowRectangle;

                    // This will combine the rectangles when the top and bottom borders coincide.  The aggregate rectangle collects
                    // individual rows into one large rectangle and places the largest contiguous rectangle possible into the
                    // region.  This simplifies the work the GDI has to do to process the invalid areas of the document.
                    if (aggregateRectangle.Left == rowRectangle.Left && aggregateRectangle.Width == rowRectangle.Width &&
                        aggregateRectangle.Bottom == rowRectangle.Top)
                    {
                        aggregateRectangle = Rectangle.Union(aggregateRectangle, rowRectangle);
                    }
                    else
                    {
                        if (!aggregateRectangle.IsEmpty)
                        {
                            region.Union(aggregateRectangle);
                        }
                        aggregateRectangle = rowRectangle;
                    }
                }

                // This will calculate the location of each of the cells in document coordinates.  If the coordinates are
                // different from the current coordinates that cell will be added to the update region, assuming the row hasn't
                // already been added.
                foreach (SpreadsheetColumn spreadsheetColumn in this.ViewColumns)
                {
                    SpreadsheetCell spreadsheetCell = spreadsheetRow[spreadsheetColumn];

                    // This is the rectangle that this cell should occupy.
                    Rectangle cellRectangle = new Rectangle(displayCursor, new Size(spreadsheetColumn.Rectangle.Width,
                                                                                    spreadsheetRow.rectangle.Height));

                    // This is the test to see if this cell needs to be redrawn.  If the row isn't valid, then we don't need
                    // to redraw the cell because it will be redrawn when the row is painted.  If the dimensions of the cell
                    // have changed, then it needs to be repainted.  Finally, if there was an original version of this cell and
                    // it isn't the same as the suggested cell, it needs to be repainted.
                    if (isRowValid && (spreadsheetCell.DisplayRectangle != cellRectangle || spreadsheetCell.IsModified))
                    {
                        // This will aggregate the cells into larger rectangles if their edges cooincide.  The large contiguous
                        // rectangles are added to the area that needs to be redrawn.
                        if (aggregateRectangle.Top == cellRectangle.Top && aggregateRectangle.Height == cellRectangle.Height &&
                            aggregateRectangle.Right == cellRectangle.Left)
                        {
                            aggregateRectangle = Rectangle.Union(aggregateRectangle, cellRectangle);
                        }
                        else
                        {
                            if (!aggregateRectangle.IsEmpty)
                            {
                                region.Union(aggregateRectangle);
                            }
                            aggregateRectangle = cellRectangle;
                        }
                    }

                    spreadsheetCell.DisplayRectangle = cellRectangle;

                    // This flag is set after the cell is measured.  The cell won't be updated again until this flag is set
                    // again.
                    spreadsheetCell.IsModified = false;

                    // Move the cursor up to the next column and test the next cell.
                    displayCursor.X += spreadsheetColumn.Rectangle.Width;
                }

                // This will reset the cursor for the next row.
                displayCursor.X  = 0;
                displayCursor.Y += spreadsheetRow.rectangle.Height;
            }

            // If all the rows and all the cells have been measured and checked for changes, then check one last time to see if
            // there is anything in the aggregate rectangel that needs to be redrawn.
            if (!aggregateRectangle.IsEmpty)
            {
                region.Union(aggregateRectangle);
            }

            // This is the height of the displayed document.
            this.displayRectangle.Height = displayCursor.Y;

            // This contains all the areas that need to be redrawn.
            return(region);
        }