DataGridParentRows.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / WinForms / Managed / System / WinForms / DataGridParentRows.cs / 1305376 / DataGridParentRows.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Windows.Forms { 
    using System.Text; 
    using System.Runtime.Remoting;
 
    using System;
    using System.Collections;

    using System.Windows.Forms; 
    using System.Security.Permissions;
 
    using System.ComponentModel; 
    using System.Drawing;
    using System.Drawing.Imaging; 
    using Microsoft.Win32;

    using System.Runtime.InteropServices;
    using System.Diagnostics; 
    using System.Runtime.Versioning;
 
    internal class DataGridParentRows { 
        // siting
        // 
        private DataGrid dataGrid;

        // ui
        // 
        // private Color backColor = DataGrid.defaultParentRowsBackColor;
        // private Color foreColor = DataGrid.defaultParentRowsForeColor; 
 
        private SolidBrush backBrush = DataGrid.DefaultParentRowsBackBrush;
        private SolidBrush foreBrush = DataGrid.DefaultParentRowsForeBrush; 

        private int borderWidth = 1;
        // private Color borderColor = SystemColors.WindowFrame;
        private Brush borderBrush = new SolidBrush(SystemColors.WindowFrame); 

        private static Bitmap rightArrow = null; 
        private static Bitmap leftArrow = null; 

        private ColorMap[] colorMap = new ColorMap[] {new ColorMap()}; 

        // private bool gridLineDots = false;
        // private Color gridLineColor = SystemColors.Control;
        // private Brush gridLineBrush = SystemBrushes.Control; 
        private Pen gridLinePen = SystemPens.Control;
 
        private int totalHeight = 0; 
        private int textRegionHeight = 0;
 

        // now that we have left and right arrows, we also have layout
        private Layout layout = new Layout();
 
        // mouse info
        // 
        // private bool overLeftArrow = false; 
        // private bool overRightArrow = false;
        private bool downLeftArrow = false; 
        private bool downRightArrow = false;

        // a horizOffset of 0 means that the layout for the parent
        // rows is left aligned. 
        // a horizOffset of 1 means that the leftmost unit of information ( let it be a
        // table name, a column name or a column value ) is not visible. 
        // a horizOffset of 2 means that the leftmost 2 units of information are not visible, and so on 
        //
        private int horizOffset = 0; 

        // storage for parent row states
        //
        private ArrayList parents = new ArrayList(); 
        private int parentsCount = 0;
        private ArrayList rowHeights = new ArrayList(); 
        AccessibleObject accessibleObject; 

        internal DataGridParentRows(DataGrid dataGrid) { 
            this.colorMap[0].OldColor = Color.Black;
            this.dataGrid = dataGrid;
            // UpdateGridLinePen();
        } 

        // =----------------------------------------------------------------- 
        // =        Properties 
        // =-----------------------------------------------------------------
 
        public AccessibleObject AccessibleObject {
            get {
                if (accessibleObject == null) {
                    accessibleObject = new DataGridParentRowsAccessibleObject(this); 
                }
                return accessibleObject; 
            } 
        }
 
        internal Color BackColor {
            get {
                return backBrush.Color;
            } 
            set {
                if (value.IsEmpty) 
                    throw new ArgumentException(SR.GetString(SR.DataGridEmptyColor, "Parent Rows BackColor")); 
                if (value != backBrush.Color) {
                    backBrush = new SolidBrush(value); 
                    Invalidate();
                }
            }
        } 

        internal SolidBrush BackBrush { 
            get { 
                return backBrush;
            } 
            set {
                if (value != backBrush) {
                    CheckNull(value, "BackBrush");
                    backBrush = value; 
                    Invalidate();
                } 
            } 
        }
 
        internal SolidBrush ForeBrush {
            get {
                return foreBrush;
            } 
            set {
                if (value != foreBrush) { 
                    CheckNull(value, "BackBrush"); 
                    foreBrush = value;
                    Invalidate(); 
                }
            }
        }
 
        // since the layout of the parentRows is computed on every paint message,
        // we can actually return true ClientRectangle coordinates 
        internal Rectangle GetBoundsForDataGridStateAccesibility(DataGridState dgs) { 
            Rectangle ret = Rectangle.Empty;
            int rectY = 0; 
            for (int i = 0; i < parentsCount; i++) {
                int height = (int) rowHeights[i];
                if (parents[i] == dgs) {
                    ret.X = layout.leftArrow.IsEmpty ? layout.data.X : layout.leftArrow.Right; 
                    ret.Height = height;
                    ret.Y = rectY; 
                    ret.Width = layout.data.Width; 
                    return ret;
                } 
                rectY += height;
            }
            return ret;
        } 

        /* 
        internal Color BorderColor { 
            get {
                return borderColor; 
            }
            set {
                if (value != borderColor) {
                    borderColor = value; 
                    Invalidate();
                } 
            } 
        }
        */ 

        internal Brush BorderBrush {
            get {
                return borderBrush; 
            }
            set { 
                if (value != borderBrush) { 
                    borderBrush = value;
                    Invalidate(); 
                }
            }
        }
 
        /*
        internal Brush GridLineBrush { 
            get { 
                return gridLineBrush;
            } 
            set {
                if (value != gridLineBrush) {
                    gridLineBrush = value;
                    UpdateGridLinePen(); 
                    Invalidate();
                } 
            } 
        }
 
        internal bool GridLineDots {
            get {
                return gridLineDots;
            } 
            set {
                if (gridLineDots != value) { 
                    gridLineDots = value; 
                    UpdateGridLinePen();
                    Invalidate(); 
                }
            }
        }
        */ 

        internal int Height { 
            get { 
                return totalHeight;
            } 
        }

        internal Color ForeColor {
            get { 
                return foreBrush.Color;
            } 
            set { 
                if (value.IsEmpty)
                    throw new ArgumentException(SR.GetString(SR.DataGridEmptyColor, "Parent Rows ForeColor")); 
                if (value != foreBrush.Color) {
                    foreBrush = new SolidBrush(value);
                    Invalidate();
                } 
            }
        } 
 
        internal bool Visible {
            get { 
                return dataGrid.ParentRowsVisible;
            }
            set {
                dataGrid.ParentRowsVisible = value; 
            }
        } 
 
        // =------------------------------------------------------------------
        // =        Methods 
        // =-----------------------------------------------------------------

        /// 
        ///  
        ///      Adds a DataGridState object to the top of the list of parents.
        ///  
        internal void AddParent(DataGridState dgs) { 
            CurrencyManager childDataSource = (CurrencyManager) dataGrid.BindingContext[dgs.DataSource, dgs.DataMember];
            parents.Add(dgs); 
            SetParentCount(parentsCount + 1);
            Debug.Assert(GetTopParent() != null, "we should have a parent at least");
        }
 
        internal void Clear() {
            for (int i = 0; i < parents.Count; i++) { 
                DataGridState dgs = parents[i] as DataGridState; 
                dgs.RemoveChangeNotification();
            } 
            parents.Clear();
            rowHeights.Clear();
            totalHeight = 0;
            SetParentCount(0); 
        }
 
        internal void SetParentCount(int count) { 
            parentsCount = count;
            dataGrid.Caption.BackButtonVisible = (parentsCount > 0) && (dataGrid.AllowNavigation); 
        }

        internal void CheckNull(object value, string propName) {
            if (value == null) 
                throw new ArgumentNullException("propName");
        } 
 
        internal void Dispose() {
            gridLinePen.Dispose(); 
        }

        /// 
        ///  
        ///      Retrieves the top most parent in the list of parents.
        ///  
        internal DataGridState GetTopParent() { 
            if (parentsCount < 1) {
                return null; 
            }
            return(DataGridState)(((ICloneable)(parents[parentsCount-1])).Clone());
        }
 
        /// 
        ///  
        ///      Determines if there are any parent rows contained in this object. 
        /// 
        internal bool IsEmpty() { 
            return parentsCount == 0;
        }

        ///  
        /// 
        ///      Similar to GetTopParent() but also removes it. 
        ///  
        internal DataGridState PopTop() {
            if (parentsCount < 1) { 
                return null;
            }

            SetParentCount(parentsCount - 1); 
            DataGridState ret = (DataGridState)parents[parentsCount];
            ret.RemoveChangeNotification(); 
            parents.RemoveAt(parentsCount); 
            return ret;
        } 

        internal void Invalidate() {
            if (dataGrid != null)
                dataGrid.InvalidateParentRows(); 
        }
 
        internal void InvalidateRect(Rectangle rect) 
        {
            if (dataGrid != null) 
            {
                Rectangle r = new Rectangle(rect.X, rect.Y, rect.Width + borderWidth, rect.Height + borderWidth);
                dataGrid.InvalidateParentRowsRect(r);
            } 
        }
 
        // called from DataGrid::OnLayout 
        internal void OnLayout() {
            if (parentsCount == rowHeights.Count) 
                return;

            int height = 0;
            if (totalHeight == 0) { 
                totalHeight += 2 * borderWidth;
            } 
 
            // figure out how tall each row's text will be
            // 
            textRegionHeight = (int)dataGrid.Font.Height + 2;

            // make the height of the Column.Font count for the height
            // of the parentRows; 
            //
            // if the user wants to programatically 
            // navigate to a relation in the constructor of the form 
            // ( ie, when the form does not process PerformLayout )
            // the grid will receive an OnLayout message when there is more 
            // than one parent in the grid
            if (parentsCount > rowHeights.Count) {
                Debug.Assert(parentsCount == rowHeights.Count + 1 || rowHeights.Count == 0, "see bug 82808 for more info, or the comment above");
                int rowHeightsCount = this.rowHeights.Count; 
                for (int i = rowHeightsCount; i < parentsCount; i++) {
                    DataGridState dgs = (DataGridState) parents[i]; 
                    GridColumnStylesCollection cols = dgs.GridColumnStyles; 

                    int colsHeight = 0; 

                    for (int j=0; j 0) {
                ResetMouseInfo(); 
                horizOffset -= 1;
                Invalidate();
            }
            else 
            {
                ResetMouseInfo(); 
                InvalidateRect(layout.leftArrow); 
            }
        } 

        private void RightArrowClick(int cellCount) {
            if (horizOffset < cellCount - 1) {
                ResetMouseInfo(); 
                horizOffset += 1;
                Invalidate(); 
            } 
            else
            { 
                ResetMouseInfo();
                InvalidateRect(layout.rightArrow);
            }
        } 

        // the only mouse clicks that are handled are 
        // the mouse clicks on the LeftArrow and RightArrow 
        //
        internal void OnMouseDown(int x, int y, bool alignToRight) { 
            if (layout.rightArrow.IsEmpty) {
                Debug.Assert(layout.leftArrow.IsEmpty, "we can't have the leftArrow w/o the rightArrow");
                return;
            } 

            int cellCount = CellCount(); 
 
            if (layout.rightArrow.Contains(x,y)) {
                // draw a nice sunken border around the right arrow area 
                // we want to keep a cell on the screen

                downRightArrow = true;
 
                if (alignToRight)
                    LeftArrowClick(cellCount); 
                else 
                    RightArrowClick(cellCount);
            } 
            else if (layout.leftArrow.Contains(x,y)) {
                downLeftArrow = true;

                if (alignToRight) 
                    RightArrowClick(cellCount);
                else 
                    LeftArrowClick(cellCount); 
            }
            else 
            {
                if (downLeftArrow)
                {
                    downLeftArrow = false; 
                    InvalidateRect(layout.leftArrow);
                } 
                if (downRightArrow) 
                {
                    downRightArrow = false; 
                    InvalidateRect(layout.rightArrow);
                }
            }
        } 

        internal void OnMouseLeave() { 
            if (downLeftArrow) 
            {
                downLeftArrow = false; 
                InvalidateRect(layout.leftArrow);
            }
            if (downRightArrow)
            { 
                downRightArrow = false;
                InvalidateRect(layout.rightArrow); 
            } 
        }
 
        internal void OnMouseMove(int x, int y) {
            /*
            if (!layout.leftArrow.IsEmpty && layout.leftArrow.Contains(x,y))
            { 
                ResetMouseInfo();
                overLeftArrow = true; 
                InvalidateRect(layout.leftArrow); 
                return;
            } 
            if (!layout.rightArrow.IsEmpty && layout.rightArrow.Contains(x,y))
            {
                ResetMouseInfo();
                overRightArrow = true; 
                InvalidateRect(layout.rightArrow);
                return; 
            } 
            */
 
            if (downLeftArrow)
            {
                downLeftArrow = false;
                InvalidateRect(layout.leftArrow); 
            }
            if (downRightArrow) 
            { 
                downRightArrow = false;
                InvalidateRect(layout.rightArrow); 
            }
        }

        internal void OnMouseUp(int x, int y) { 
            ResetMouseInfo();
            if (!layout.rightArrow.IsEmpty && layout.rightArrow.Contains(x,y)) 
            { 
                InvalidateRect(layout.rightArrow);
                return; 
            }
            if (!layout.leftArrow.IsEmpty && layout.leftArrow.Contains(x,y))
            {
                InvalidateRect(layout.leftArrow); 
                return;
            } 
        } 

        internal void OnResize(Rectangle oldBounds) { 
            Invalidate();
        }

        ///  
        /// 
        ///      Paints the parent rows 
        ///  
        internal void Paint(Graphics g, Rectangle visualbounds, bool alignRight) {
            Rectangle bounds = visualbounds; 
            // Paint the border around our bounds
            if (borderWidth > 0) {
                PaintBorder(g, bounds);
                bounds.Inflate(-borderWidth, -borderWidth); 
            }
 
            PaintParentRows(g, bounds, alignRight); 
        }
 
        private void PaintBorder(Graphics g, Rectangle bounds) {
            Rectangle border = bounds;

            // top 
            border.Height = borderWidth;
            g.FillRectangle(borderBrush, border); 
 
            // bottom
            border.Y = bounds.Bottom - borderWidth; 
            g.FillRectangle(borderBrush, border);

            // left
            border = new Rectangle(bounds.X, bounds.Y + borderWidth, 
                                   borderWidth, bounds.Height - 2*borderWidth);
            g.FillRectangle(borderBrush, border); 
 
            // right
            border.X = bounds.Right - borderWidth; 
            g.FillRectangle(borderBrush, border);
        }

        // will return the width of the text box that will fit all the 
        // tables names
        private int GetTableBoxWidth(Graphics g, Font font) { 
            // try to make the font BOLD 
            Font textFont = font;
            try { 
                textFont = new Font(font, FontStyle.Bold);
            }
            catch {
            } 
            int width = 0;
            for (int row = 0; row < parentsCount; row ++) { 
                DataGridState dgs = (DataGridState) parents[row]; 
                // Graphics.MeasureString(...) returns different results for ": " than for " :"
                // 
                string displayTableName = dgs.ListManager.GetListName() + " :";
                int size = (int) g.MeasureString(displayTableName, textFont).Width;
                width = Math.Max(size, width);
            } 

            return width; 
        } 

        // will return the width of the text box that will 
        // fit all the column names
        private int GetColBoxWidth(Graphics g, Font font, int colNum) {
            int width = 0;
 
            for (int  row = 0; row < parentsCount; row ++) {
                DataGridState dgs = (DataGridState) parents[row]; 
                GridColumnStylesCollection columns = dgs.GridColumnStyles; 
                if (colNum < columns.Count) {
                    // Graphics.MeasureString(...) returns different results for ": " than for " :" 
                    //
                    string colName = columns[colNum].HeaderText + " :";
                    int size = (int) g.MeasureString(colName, font).Width;
                    width = Math.Max(size, width); 
                }
            } 
 
            return width;
        } 


        // will return the width of the best fit for the column
        // 
        private int GetColDataBoxWidth(Graphics g, int colNum) {
            int width = 0; 
            for (int row = 0; row < parentsCount; row ++) { 
                DataGridState dgs = (DataGridState) parents[row];
                GridColumnStylesCollection columns = dgs.GridColumnStyles; 
                if (colNum < columns.Count) {
                    object value = columns[colNum].GetColumnValueAtRow((CurrencyManager) dataGrid.BindingContext[dgs.DataSource, dgs.DataMember],
                                                                        dgs.LinkingRow.RowNumber);
                    int size = columns[colNum].GetPreferredSize(g, value).Width; 
                    width = Math.Max(size, width);
                } 
            } 
            return width;
        } 

        // will return the count of the table with the largest number of columns
        private int ColsCount() {
            int colNum = 0; 
            for (int row = 0; row < parentsCount; row ++) {
                DataGridState dgs = (DataGridState) parents[row]; 
                colNum = Math.Max(colNum, dgs.GridColumnStyles.Count); 
            }
            return colNum; 
        }

        // will return the total width required to paint the parentRows
        private int TotalWidth(int tableNameBoxWidth, int[] colsNameWidths, int[] colsDataWidths) { 
            int totalWidth = 0;
            totalWidth += tableNameBoxWidth; 
            Debug.Assert(colsNameWidths.Length == colsDataWidths.Length, "both arrays are as long as the largest column count in dgs"); 
            for (int i = 0; i < colsNameWidths.Length; i ++) {
                totalWidth += colsNameWidths[i]; 
                totalWidth += colsDataWidths[i];
            }

            // let 3 pixels in between datacolumns 
            // see DonnaWa
            totalWidth += 3 * (colsNameWidths.Length - 1); 
            return totalWidth; 
        }
 
        // computes the layout for the parent rows
        //
        private void ComputeLayout(Rectangle bounds, int tableNameBoxWidth, int[] colsNameWidths, int[] colsDataWidths) {
            int totalWidth = TotalWidth(tableNameBoxWidth, colsNameWidths, colsDataWidths); 
            if (totalWidth > bounds.Width) {
                layout.leftArrow = new Rectangle(bounds.X, bounds.Y, 15, bounds.Height); 
                layout.data = new Rectangle(layout.leftArrow.Right, bounds.Y, bounds.Width - 30, bounds.Height); 
                layout.rightArrow = new Rectangle(layout.data.Right, bounds.Y, 15, bounds.Height);
            } 
            else {
                layout.data = bounds;
                layout.leftArrow = Rectangle.Empty;
                layout.rightArrow = Rectangle.Empty; 
            }
        } 
 
        private void PaintParentRows(Graphics g, Rectangle bounds, bool alignToRight) {
            // variables needed for aligning the table and column names 
            int tableNameBoxWidth = 0;
            int numCols = ColsCount();
            int[] colsNameWidths = new int[numCols];
            int[] colsDataWidths = new int[numCols]; 

            // compute the size of the box that will contain the tableName 
            // 
            if (dataGrid.ParentRowsLabelStyle == DataGridParentRowsLabelStyle.TableName ||
                dataGrid.ParentRowsLabelStyle == DataGridParentRowsLabelStyle.Both) { 
                tableNameBoxWidth = GetTableBoxWidth(g, dataGrid.Font);
            }

            // initialiaze the arrays that contain the column names and the column size 
            //
            for (int i = 0; i < numCols; i++) { 
                if (dataGrid.ParentRowsLabelStyle == DataGridParentRowsLabelStyle.ColumnName || 
                    dataGrid.ParentRowsLabelStyle == DataGridParentRowsLabelStyle.Both) {
                    colsNameWidths[i] = GetColBoxWidth(g, dataGrid.Font, i); 
                }
                else {
                    colsNameWidths[i] = 0;
                } 
                colsDataWidths[i] = GetColDataBoxWidth(g, i);
            } 
 
            // compute the layout
            // 
            ComputeLayout(bounds, tableNameBoxWidth, colsNameWidths, colsDataWidths);

            // paint the navigation arrows, if necessary
            // 
            if (!layout.leftArrow.IsEmpty)
            { 
                g.FillRectangle(BackBrush, layout.leftArrow); 
                PaintLeftArrow(g, layout.leftArrow, alignToRight);
            } 

            // paint the parent rows:
            //
            Rectangle rowBounds = layout.data; 
            for (int row = 0; row < parentsCount; ++row) {
                rowBounds.Height = (int) rowHeights[row]; 
                if (rowBounds.Y > bounds.Bottom) 
                    break;
                int paintedWidth = PaintRow(g, rowBounds, row, dataGrid.Font, alignToRight, tableNameBoxWidth, colsNameWidths, colsDataWidths); 
                if (row == parentsCount-1)
                    break;

                // draw the grid line below 
                g.DrawLine(gridLinePen, rowBounds.X, rowBounds.Bottom,
                           rowBounds.X + paintedWidth, 
                           rowBounds.Bottom); 
                rowBounds.Y += rowBounds.Height;
            } 

            if (!layout.rightArrow.IsEmpty)
            {
                g.FillRectangle(BackBrush, layout.rightArrow); 
                PaintRightArrow(g, layout.rightArrow, alignToRight);
            } 
        } 

        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        private Bitmap GetBitmap(string bitmapName, Color transparentColor) {
            Bitmap b = null;
            try { 
                b = new Bitmap(typeof(DataGridParentRows), bitmapName);
                b.MakeTransparent(transparentColor); 
            } 
            catch (Exception e) {
                Debug.Fail("Failed to load bitmap: " + bitmapName, e.ToString()); 
            }
            return b;
        }
 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        private Bitmap GetRightArrowBitmap() 
        {
            if (rightArrow == null) 
                rightArrow = GetBitmap("DataGridParentRows.RightArrow.bmp", Color.White);
            return rightArrow;
        }
 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        private Bitmap GetLeftArrowBitmap() 
        {
            if (leftArrow == null) 
                leftArrow = GetBitmap("DataGridParentRows.LeftArrow.bmp", Color.White);
            return leftArrow;
        }
 
        private void PaintBitmap(Graphics g, Bitmap b, Rectangle bounds)
        { 
            // center the bitmap in the bounds: 
            int bmpX = bounds.X + (bounds.Width - b.Width) / 2;
            int bmpY = bounds.Y + (bounds.Height - b.Height) / 2; 
            Rectangle bmpRect = new Rectangle(bmpX, bmpY, b.Width, b.Height);

            g.FillRectangle(BackBrush, bmpRect);
 
            // now draw the bitmap
            ImageAttributes attr = new ImageAttributes(); 
            this.colorMap[0].NewColor = this.ForeColor; 
            attr.SetRemapTable(colorMap, ColorAdjustType.Bitmap);
            g.DrawImage(b, bmpRect, 0, 0, bmpRect.Width, bmpRect.Height,GraphicsUnit.Pixel, attr); 
            attr.Dispose();
        }

        /* 
        private void PaintOverButton(Graphics g, Rectangle bounds)
        { 
        } 
        */
 
        private void PaintDownButton(Graphics g, Rectangle bounds)
        {
            g.DrawLine(Pens.Black, bounds.X, bounds.Y, bounds.X + bounds.Width, bounds.Y);  // the top
            g.DrawLine(Pens.White, bounds.X + bounds.Width, bounds.Y, bounds.X + bounds.Width, bounds.Y + bounds.Height);  // the right side 
            g.DrawLine(Pens.White, bounds.X + bounds.Width, bounds.Y + bounds.Height, bounds.X, bounds.Y + bounds.Height);  // the right side
            g.DrawLine(Pens.Black, bounds.X, bounds.Y + bounds.Height, bounds.X, bounds.Y);  // the left side 
        } 

        private void PaintLeftArrow(Graphics g, Rectangle bounds, bool alignToRight) 
        {
            Bitmap bmp = GetLeftArrowBitmap();
            // paint the border around this bitmap if this is the case
            // 
            /*
            if (overLeftArrow) 
            { 
                Debug.Assert(!downLeftArrow, "can both of those happen?");
                PaintOverButton(g, bounds); 
                layout.leftArrow.Inflate(-1,-1);
            }
            */
            if (downLeftArrow) 
            {
                PaintDownButton(g, bounds); 
                layout.leftArrow.Inflate(-1,-1); 
                lock (bmp) {
                    PaintBitmap(g, bmp, bounds); 
                }
                layout.leftArrow.Inflate(1,1);
            }
            else { 
                lock (bmp) {
                    PaintBitmap(g, bmp, bounds); 
                } 
            }
        } 

        private void PaintRightArrow(Graphics g, Rectangle bounds, bool alignToRight)
        {
            Bitmap bmp = GetRightArrowBitmap(); 
            // paint the border around this bitmap if this is the case
            // 
            /* 
            if (overRightArrow)
            { 
                Debug.Assert(!downRightArrow, "can both of those happen?");
                PaintOverButton(g, bounds);
                layout.rightArrow.Inflate(-1,-1);
            } 
            */
            if (downRightArrow) 
            { 
                PaintDownButton(g, bounds);
                layout.rightArrow.Inflate(-1,-1); 
                lock (bmp) {
                    PaintBitmap(g, bmp, bounds);
                }
                layout.rightArrow.Inflate(1,1); 
            }
            else { 
                lock (bmp) { 
                    PaintBitmap(g, bmp, bounds);
                } 
            }
        }

        private int PaintRow(Graphics g, Rectangle bounds, int row, Font font, bool alignToRight, 
                             int tableNameBoxWidth, int[] colsNameWidths, int[] colsDataWidths) {
            DataGridState dgs = (DataGridState) parents[row]; 
            Rectangle paintBounds = bounds; 
            Rectangle rowBounds = bounds;
            paintBounds.Height = (int) rowHeights[row]; 
            rowBounds.Height = (int) rowHeights[row];

            int paintedWidth = 0;
            // used for scrolling: when paiting, we will skip horizOffset cells in the dataGrid ParentRows 
            int skippedCells = 0;
 
            // paint the table name 
            if ( dataGrid.ParentRowsLabelStyle == DataGridParentRowsLabelStyle.TableName ||
                 dataGrid.ParentRowsLabelStyle == DataGridParentRowsLabelStyle.Both) { 
                if (skippedCells < horizOffset) {
                    // skip this
                    skippedCells ++;
                } 
                else {
                    paintBounds.Width = Math.Min(paintBounds.Width, tableNameBoxWidth); 
                    paintBounds.X = MirrorRect(bounds, paintBounds, alignToRight); 
                    string displayTableName = dgs.ListManager.GetListName() + ": ";
                    PaintText(g, paintBounds, displayTableName, font, true, alignToRight);      // true is for painting bold 
                    paintedWidth += paintBounds.Width;
                }
            }
 
            if (paintedWidth >= bounds.Width)
                return bounds.Width;        // we painted everything 
 
            rowBounds.Width -= paintedWidth;
            rowBounds.X += alignToRight ? 0 : paintedWidth; 
            paintedWidth += PaintColumns(g, rowBounds, dgs, font, alignToRight, colsNameWidths, colsDataWidths, skippedCells);

            // paint the possible space left after columns
            if (paintedWidth < bounds.Width) { 
                paintBounds.X = bounds.X + paintedWidth;
                paintBounds.Width = bounds.Width - paintedWidth; 
                paintBounds.X = MirrorRect(bounds, paintBounds, alignToRight); 
                g.FillRectangle(BackBrush, paintBounds);
            } 
            return paintedWidth;
        }

        private int PaintColumns(Graphics g, Rectangle bounds, DataGridState dgs, Font font, bool alignToRight, 
                                 int[] colsNameWidths, int[] colsDataWidths, int skippedCells) {
            Rectangle paintBounds = bounds; 
            Rectangle rowBounds = bounds; 
            GridColumnStylesCollection cols = dgs.GridColumnStyles;
            int cx = 0; 

            for (int i = 0; i < cols.Count; i ++) {
                if (cx >= bounds.Width)
                    break; 

                // paint the column name, if we have to 
                if (dataGrid.ParentRowsLabelStyle == DataGridParentRowsLabelStyle.ColumnName || 
                    dataGrid.ParentRowsLabelStyle == DataGridParentRowsLabelStyle.Both) {
                    if (skippedCells < horizOffset) { 
                        // skip this column
                    }
                    else {
                        paintBounds.X = bounds.X + cx; 
                        paintBounds.Width = Math.Min(bounds.Width - cx, colsNameWidths[i]);
                        paintBounds.X = MirrorRect(bounds, paintBounds, alignToRight); 
 
                        string colName = cols[i].HeaderText + ": ";
                        PaintText(g, paintBounds, colName, font, false, alignToRight);      // false is for not painting bold 

                        cx += paintBounds.Width;
                    }
                } 

                if (cx >= bounds.Width) 
                    break; 

                if (skippedCells < horizOffset) { 
                    // skip this cell
                    skippedCells ++;
                } else {
                    // paint the cell contents 
                    paintBounds.X = bounds.X + cx;
                    paintBounds.Width = Math.Min(bounds.Width - cx, colsDataWidths[i]); 
                    paintBounds.X = MirrorRect(bounds, paintBounds, alignToRight); 

                    // when we paint the data grid parent rows, we want to paint the data at the position 
                    // stored in the currency manager.
                    cols[i].Paint(g, paintBounds, (CurrencyManager) dataGrid.BindingContext[dgs.DataSource, dgs.DataMember],
                                    dataGrid.BindingContext[dgs.DataSource, dgs.DataMember].Position, BackBrush, ForeBrush, alignToRight);
 
                    cx += paintBounds.Width;
 
                    // draw the line to the right (or left, according to alignRight) 
                    //
                    g.DrawLine(new Pen(SystemColors.ControlDark), 
                               alignToRight ? paintBounds.X : paintBounds.Right,
                               paintBounds.Y,
                               alignToRight ? paintBounds.X : paintBounds.Right,
                               paintBounds.Bottom); 

                    // this is how wide the line is.... 
                    cx++; 

                    // put 3 pixels in between columns 
                    // see DonnaWa
                    //
                    if ( i < cols.Count - 1)
                    { 
                        paintBounds.X = bounds.X + cx;
                        paintBounds.Width = Math.Min(bounds.Width - cx, 3); 
                        paintBounds.X = MirrorRect(bounds, paintBounds, alignToRight); 

                        g.FillRectangle(BackBrush, paintBounds); 
                        cx += 3;
                    }
                }
            } 

            return cx; 
        } 

        ///  
        /// 
        ///      Draws on the screen the text. It is used only to paint the Table Name and the column Names
        ///      Returns the width of bounding rectangle that was passed in
        ///  
        private int PaintText(Graphics g, Rectangle textBounds, string text, Font font, bool bold, bool alignToRight) {
            Font textFont = font; 
            if (bold) 
                try {
                    textFont = new Font(font, FontStyle.Bold); 
                } catch {}
            else
                textFont = font;
 
            // right now, we paint the entire box, cause it will be used anyway
            g.FillRectangle(BackBrush, textBounds); 
            StringFormat format = new StringFormat(); 
            if (alignToRight) {
                format.FormatFlags |= StringFormatFlags.DirectionRightToLeft; 
                format.Alignment = StringAlignment.Far;
            }
            format.FormatFlags |= StringFormatFlags.NoWrap;
            // part 1, section 3: put the table and the column name in the 
            // parent rows at the same height as the dataGridTextBoxColumn draws the string
            // 
            textBounds.Offset(0, 2); 
            textBounds.Height -= 2;
            g.DrawString(text, textFont, ForeBrush, textBounds, format); 
            format.Dispose();
            return textBounds.Width;

        } 

        // will return the X coordinate of the containedRect mirrored within the surroundingRect 
        // according to the value of alignToRight 
        private int MirrorRect(Rectangle surroundingRect, Rectangle containedRect, bool alignToRight) {
            Debug.Assert(containedRect.X >= surroundingRect.X && containedRect.Right <= surroundingRect.Right, "containedRect is not contained in surroundingRect"); 
            if (alignToRight)
                return surroundingRect.Right - containedRect.Right + surroundingRect.X;
            else
                return containedRect.X; 
        }
 
        private class Layout { 
            public Rectangle data;
            public Rectangle leftArrow; 
            public Rectangle rightArrow;

            public Layout() {
                data = Rectangle.Empty; 
                leftArrow = Rectangle.Empty;
                rightArrow = Rectangle.Empty; 
            } 

            public override string ToString() { 
                StringBuilder sb = new StringBuilder(200);
                sb.Append("ParentRows Layout: \n");
                sb.Append("data = ");
                sb.Append(data.ToString()); 
                sb.Append("\n leftArrow = ");
                sb.Append(leftArrow.ToString()); 
                sb.Append("\n rightArrow = "); 
                sb.Append(rightArrow.ToString());
                sb.Append("\n"); 

                return sb.ToString();
            }
        } 

        [ComVisible(true)] 
        protected internal class DataGridParentRowsAccessibleObject : AccessibleObject { 
            DataGridParentRows owner = null;
 
            public DataGridParentRowsAccessibleObject(DataGridParentRows owner) : base() {
                Debug.Assert(owner != null, "DataGridParentRowsAccessibleObject must have a valid owner");
                this.owner = owner;
            } 

            internal DataGridParentRows Owner { 
                get { 
                    return owner;
                } 
            }

            public override Rectangle Bounds {
                get { 
                    return owner.dataGrid.RectangleToScreen(owner.dataGrid.ParentRowsBounds);
                } 
            } 

            public override string DefaultAction { 
                get {
                    return SR.GetString(SR.AccDGNavigateBack);
                }
            } 

            public override string Name { 
                get { 
                    return SR.GetString(SR.AccDGParentRows);
                } 
            }

            public override AccessibleObject Parent {
                [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] 
                get {
                    return owner.dataGrid.AccessibilityObject; 
                } 
            }
 
            public override AccessibleRole Role {
                get {
                    return AccessibleRole.List;
                } 
            }
 
            public override AccessibleStates State { 
                get {
                    AccessibleStates state = AccessibleStates.ReadOnly; 

                    if (owner.parentsCount == 0) {
                        state |= AccessibleStates.Invisible;
                    } 
                    if (owner.dataGrid.ParentRowsVisible) {
                        state |= AccessibleStates.Expanded; 
                    } 
                    else {
                        state |= AccessibleStates.Collapsed; 
                    }

                    return state;
                } 
            }
 
            public override string Value { 
                [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
                get { 
                    return null;
                }
            }
 
            [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
            public override void DoDefaultAction() { 
                owner.dataGrid.NavigateBack(); 
            }
 
            public override AccessibleObject GetChild(int index) {
                return ((DataGridState)owner.parents[index]).ParentRowAccessibleObject;
            }
 
            public override int GetChildCount() {
                return owner.parentsCount; 
            } 

            ///  
            /// 
            ///      Returns the currently focused child, if any.
            ///      Returns this if the object itself is focused.
            ///  
            public override AccessibleObject GetFocused() {
                return null; 
            } 

            internal AccessibleObject GetNext(AccessibleObject child) { 
                int children = GetChildCount();
                bool hit = false;

                for (int i=0; i=0; i--) {
                    if (hit) {
                        return GetChild(i); 
                    }
                    if (GetChild(i) == child) { 
                        hit = true; 
                    }
                } 

                return null;
            }
 

            ///  
            ///  
            ///      Navigate to the next or previous grid entry.
            ///  
            [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
            public override AccessibleObject Navigate(AccessibleNavigation navdir) {
                switch (navdir) {
                    case AccessibleNavigation.Right: 
                    case AccessibleNavigation.Next:
                    case AccessibleNavigation.Down: 
                        return Parent.GetChild(1); 
                    case AccessibleNavigation.Up:
                    case AccessibleNavigation.Left: 
                    case AccessibleNavigation.Previous:
                        return Parent.GetChild(GetChildCount() - 1);
                    case AccessibleNavigation.FirstChild:
                        if (GetChildCount() > 0) { 
                            return GetChild(0);
                        } 
                        break; 
                    case AccessibleNavigation.LastChild:
                        if (GetChildCount() > 0) { 
                            return GetChild(GetChildCount() - 1);
                        }
                        break;
 
                }
 
                return null; 

            } 

            [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
            public override void Select(AccessibleSelection flags) {
            } 
        }
    } 
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK