DataGridRelationshipRow.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / WinForms / Managed / System / WinForms / DataGridRelationshipRow.cs / 1 / DataGridRelationshipRow.cs

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

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

    using System; 
    using System.Runtime.InteropServices;
    using System.Security.Permissions;

    using System.Windows.Forms; 
    using System.ComponentModel;
    using System.Drawing; 
 
    using Microsoft.Win32;
    using System.Diagnostics; 
    using System.Collections;
    using System.Globalization;

    ///  
    /// 
    ///      This class fully encapsulates the painting logic for a row 
    ///      appearing in a DataGrid. 
    /// 
    internal class DataGridRelationshipRow : DataGridRow { 
        private const bool defaultOpen         = false;
        private const int  expandoBoxWidth     = 14;
        private const int  indentWidth         = 20;
        // private const int  relationshipSpacing = 1; 
        private const int  triangleSize        = 5;
 
        private bool expanded         = defaultOpen; 
        // private bool hasRelationships = false;
        // private Font linkFont = null; 
        // private new DataGrid dataGrid; // Currently used only to obtain a Graphics object for measuring text

        // private Rectangle relationshipRect   = Rectangle.Empty;
        // private int       relationshipHeight = 0; 

        // relationships 
        // we should get this directly from the dgTable. 
        // private ArrayList     relationships;
        // private int            focusedRelation = -1; 
        // private int          focusedTextWidth;

        public DataGridRelationshipRow(DataGrid dataGrid, DataGridTableStyle dgTable, int rowNumber)
        : base(dataGrid, dgTable, rowNumber) { 
            // this.dataGrid = dataGrid;
            // linkFont = dataGrid.LinkFont; 
            // relationshipHeight = dataGrid.LinkFontHeight + this.dgTable.relationshipSpacing; 

            // if (DataGrid.AllowNavigation) { 
            //     hasRelationships = dgTable.RelationsList.Count > 0;
            // }
        }
 
        internal protected override int MinimumRowHeight(GridColumnStylesCollection cols) {
            /* 
            if (DataGrid != null && DataGrid.LinkFontHeight + this.dgTable.relationshipSpacing != relationshipHeight) { 
                relationshipRect = Rectangle.Empty;
                relationshipHeight = DataGrid.LinkFontHeight + this.dgTable.relationshipSpacing; 
            }
            */

            return base.MinimumRowHeight(cols) + (this.expanded ? GetRelationshipRect().Height : 0); 
        }
 
        internal protected override int MinimumRowHeight(DataGridTableStyle dgTable) { 
            /*
            if (DataGrid != null && DataGrid.LinkFontHeight + this.dgTable.relationshipSpacing != relationshipHeight) { 
                relationshipRect = Rectangle.Empty;
                relationshipHeight = DataGrid.LinkFontHeight + this.dgTable.relationshipSpacing;
            }
            */ 

            return base.MinimumRowHeight(dgTable) + (this.expanded ? GetRelationshipRect().Height : 0); 
        } 

        // =----------------------------------------------------------------- 
        // =        Properties
        // =-----------------------------------------------------------------

        public virtual bool Expanded { 
            get {
                return expanded; 
            } 
            set {
                if (expanded == value) 
                    return;
                if (expanded)
                    Collapse();
                else 
                    Expand();
            } 
        } 

        /* 
        private Color BorderColor {
            get {
                if (DataGrid == null)
                    return Color.Empty; 
                return DataGrid.GridLineColor;
            } 
        } 
        */
 
#if FALSE
        private int BorderWidth {
            get {
                DataGrid dataGrid = this.DataGrid; 
                if (dataGrid == null)
                    return 0; 
                // if the user set the GridLineStyle property on the dataGrid. 
                // then use the value of that property
                DataGridLineStyle gridStyle; 
                int gridLineWidth;
                if (this.dgTable.IsDefault) {
                    gridStyle = this.DataGrid.GridLineStyle;
                    gridLineWidth = this.DataGrid.GridLineWidth; 
                } else {
                    gridStyle = this.dgTable.GridLineStyle; 
                    gridLineWidth = this.dgTable.GridLineWidth; 
                }
 
                if (gridStyle == DataGridLineStyle.None)
                    return 0;

                return gridLineWidth; 
            }
        } 
#endif //FALSE 

        private int FocusedRelation { 
            get {
                return this.dgTable.FocusedRelation;
            }
            set { 
                dgTable.FocusedRelation = value;
            } 
        } 

        // =------------------------------------------------------------------ 
        // =        Methods
        // =-----------------------------------------------------------------

        private void Collapse() { 
            Debug.Assert(this.dgTable.DataGrid.AllowNavigation, "how can the user collapse the relations if the grid does not allow navigation?");
            if (expanded) { 
                expanded = false; 
                // relationshipRect = Rectangle.Empty;
                FocusedRelation = -1; 
                DataGrid.OnRowHeightChanged(this);
            }
        }
 
        protected override AccessibleObject CreateAccessibleObject() {
            return new DataGridRelationshipRowAccessibleObject(this); 
        } 

 
        private void Expand() {
            Debug.Assert(this.dgTable.DataGrid.AllowNavigation, "how can the user expand the relations if the grid does not allow navigation?");
            if (expanded == false
                && DataGrid != null 
                && this.dgTable != null
                && this.dgTable.RelationsList.Count > 0) { 
                expanded = true; 
                FocusedRelation = -1;
 
                // relationshipRect = Rectangle.Empty;
                DataGrid.OnRowHeightChanged(this);
            }
        } 

        public override int Height { 
            get { 
                int height = base.Height;
                if (expanded) 
                    return height + GetRelationshipRect().Height;
                else
                    return height;
            } 
            set {
                // we should use the RelationshipRect only when the row is expanded 
                if (expanded) 
                    base.Height = value - GetRelationshipRect().Height;
                else 
                    base.Height = value;
            }
        }
 
        // so the edit box will not paint under the
        // grid line of the row 
        public override Rectangle GetCellBounds(int col) { 
            Rectangle cellBounds = base.GetCellBounds(col);
            // decrement base.Height by 1, so the edit box will not 
            // paint over the bottom line.
            cellBounds.Height = base.Height - 1;
            return cellBounds;
        } 

        ///  
        ///  
        ///      Given an origin, this procedure returns
        ///      a rectangle that describes the location of an outline box. 
        /// 
        /// 
        private Rectangle GetOutlineRect(int xOrigin, int yOrigin) {
            Rectangle outline = new Rectangle(xOrigin + 2, 
                                              yOrigin + 2,
                                              9, 
                                              9); 
            return outline;
        } 

        public override Rectangle GetNonScrollableArea() {
            if (expanded) {
                return GetRelationshipRect(); 
            }
            else 
                return Rectangle.Empty; 
        }
 
        private Rectangle GetRelationshipRect() {
            Debug.Assert(this.expanded, "we should need this rectangle only when the row is expanded");
            Rectangle ret = this.dgTable.RelationshipRect;
            ret.Y = base.Height - this.dgTable.BorderWidth; 
            return ret;
        } 
 
#if FALSE
        private Rectangle GetRelationshipRect() { 
            if (relationshipRect.IsEmpty) {
                Debug.WriteLineIf(CompModSwitches.DGRelationShpRowLayout.TraceVerbose, "GetRelationshipRect grinding away");
                if (!expanded) {
                    return(relationshipRect = new Rectangle(0,0,0,0)); 
                }
                Graphics g = DataGrid.CreateGraphicsInternal(); 
                relationshipRect = new Rectangle(); 
                relationshipRect.X = 0; //indentWidth;
                relationshipRect.Y = base.Height - this.dgTable.BorderWidth; 

                // Determine the width of the widest relationship name
                int longestRelationship = 0;
                for (int r = 0; r < this.dgTable.RelationsList.Count; ++r) { 
                    int rwidth = (int) Math.Ceiling(g.MeasureString(((string) this.dgTable.RelationsList[r]), this.DataGrid.LinkFont).Width);
                    if (rwidth > longestRelationship) 
                        longestRelationship = rwidth; 
                }
 
                g.Dispose();

                relationshipRect.Width = longestRelationship + 5;
                relationshipRect.Width += 2; // relationshipRect border; 
                relationshipRect.Height = this.dgTable.BorderWidth + relationshipHeight * this.dgTable.RelationsList.Count;
                relationshipRect.Height += 2; // relationship border 
                if (this.dgTable.RelationsList.Count > 0) 
                    relationshipRect.Height += 2 * System.Windows.Forms.DataGridTableStyle.relationshipSpacing;
            } 
            return relationshipRect;
        }

#endif// FALSE 

        private Rectangle GetRelationshipRectWithMirroring() { 
            Rectangle relRect = GetRelationshipRect(); 
            bool rowHeadersVisible = this.dgTable.IsDefault ? this.DataGrid.RowHeadersVisible : this.dgTable.RowHeadersVisible;
            if (rowHeadersVisible) { 
                int rowHeaderWidth = this.dgTable.IsDefault ? this.DataGrid.RowHeaderWidth : this.dgTable.RowHeaderWidth;
                relRect.X += DataGrid.GetRowHeaderRect().X + rowHeaderWidth;
            }
            relRect.X = MirrorRelationshipRectangle(relRect, DataGrid.GetRowHeaderRect(), DataGrid.RightToLeft == RightToLeft.Yes); 
            return relRect;
        } 
 
        /// 
        ///  
        ///      Called by the DataGrid when a click occurs in the row's client
        ///      area.  The coordinates are normalized to the rectangle's top
        ///      left point.
        ///  
        private bool PointOverPlusMinusGlyph(int x, int y, Rectangle rowHeaders, bool alignToRight) {
            if (dgTable == null || dgTable.DataGrid == null || !dgTable.DataGrid.AllowNavigation) 
                return false; 
            Rectangle insideRowHeaders = rowHeaders;
            if (!this.DataGrid.FlatMode) { 
                insideRowHeaders.Inflate(-1,-1);
            }

            Rectangle outline = GetOutlineRect(insideRowHeaders.Right - expandoBoxWidth, 0); 

            outline.X = MirrorRectangle(outline.X, outline.Width, insideRowHeaders, alignToRight); 
 
            return outline.Contains(x,y);
        } 

        public override bool OnMouseDown(int x, int y, Rectangle rowHeaders, bool alignToRight) {
            bool rowHeadersVisible = this.dgTable.IsDefault ? this.DataGrid.RowHeadersVisible : this.dgTable.RowHeadersVisible;
            if (rowHeadersVisible) { 
                if (PointOverPlusMinusGlyph(x,y,rowHeaders, alignToRight)) {
                    if (this.dgTable.RelationsList.Count == 0) { 
                        return false; 
                    }
                    else if (expanded) { 
                        Collapse();
                    }
                    else {
                        Expand(); 
                    }
                    DataGrid.OnNodeClick(EventArgs.Empty); 
                    return true; 
                }
            } 

            if (!expanded)
                return base.OnMouseDown(x, y, rowHeaders, alignToRight);
 
            // hit test for relationships
            Rectangle relRect = GetRelationshipRectWithMirroring(); 
 
            if (relRect.Contains(x, y)) {
                int r = RelationFromY(y); 
                if (r != -1) {
                    // first, reset the FocusedRelation
                    FocusedRelation = -1;
                    DataGrid.NavigateTo(((string)this.dgTable.RelationsList[r]), this, true); 
                }
                // DataGrid.OnLinkClick(EventArgs.Empty); 
                return true; 
            }
 
            return base.OnMouseDown(x, y, rowHeaders, alignToRight);
        }

        public override bool OnMouseMove(int x, int y, Rectangle rowHeaders, bool alignToRight) { 
            if (!expanded)
                return false; 
 
            Rectangle relRect = GetRelationshipRectWithMirroring();
 
            if (relRect.Contains(x, y)) {
                this.DataGrid.Cursor = Cursors.Hand;
                return true;
            } 

            this.DataGrid.Cursor = Cursors.Default; 
            return base.OnMouseMove(x, y, rowHeaders, alignToRight); 
        }
 
        // this function will not invalidate all of the
        // row
        public override void OnMouseLeft(Rectangle rowHeaders, bool alignToRight) {
            if (!expanded) 
                return;
 
            Rectangle relRect = GetRelationshipRect(); 
            relRect.X += rowHeaders.X + this.dgTable.RowHeaderWidth;
            relRect.X = MirrorRelationshipRectangle(relRect, rowHeaders, alignToRight); 

            if (FocusedRelation != -1) {
                InvalidateRowRect(relRect);
                FocusedRelation = -1; 
            }
        } 
 
        public override void OnMouseLeft() {
            if (!expanded) 
                return;

            if (FocusedRelation != -1) {
                InvalidateRow(); 
                FocusedRelation = -1;
            } 
            base.OnMouseLeft(); 
        }
 
        /// 
        /// 
        ///      Called by the DataGrid when a keypress occurs on a row with "focus."
        ///  
        public override bool OnKeyPress(Keys keyData) {
            // ignore the shift key if it is not paired w/ the TAB key 
            if ((keyData & Keys.Modifiers) == Keys.Shift && (keyData & Keys.KeyCode) != Keys.Tab) 
                return false;
 
            switch (keyData & Keys.KeyCode) {
                case Keys.F5:
                    if (dgTable == null || dgTable.DataGrid == null || !dgTable.DataGrid.AllowNavigation)
                        return false; 
                    if (expanded)
                        Collapse(); 
                    else 
                        Expand();
                    FocusedRelation = -1; 
                    return true;

                // to make the gridTest run w/ the numLock key on
                // 
                case Keys.NumLock:
                    if (FocusedRelation != -1) 
                        return false; 
                    else
                        return base.OnKeyPress(keyData); 
                case Keys.Enter:
                    if (FocusedRelation != -1) {
                        // somebody set the relation number up already
                        // navigate to the relation 
                        DataGrid.NavigateTo(((string)this.dgTable.RelationsList[FocusedRelation]), this, true);
 
                        // now reset the FocusedRelation 
                        FocusedRelation = -1;
                        return true; 
                    }
                    else
                        return false;
 
                case Keys.Tab:
                    return false; 
 
                default:
                    FocusedRelation = -1; 
                    return base.OnKeyPress(keyData);
            }
        }
 
        // will reset the FocusedRelation and will invalidate the
        // rectangle so that the linkFont is no longer shown 
        internal override void LoseChildFocus(Rectangle rowHeaders, bool alignToRight) { 
            // we only invalidate stuff if the row is expanded.
            if (FocusedRelation == -1 || !expanded) 
                return;

            FocusedRelation = -1;
            Rectangle relRect = GetRelationshipRect(); 
            relRect.X += rowHeaders.X + this.dgTable.RowHeaderWidth;
            relRect.X = MirrorRelationshipRectangle(relRect, rowHeaders, alignToRight); 
            InvalidateRowRect(relRect); 
        }
 
        // here is the logic for FOCUSED:
        //
        // first the dataGrid gets the KeyPress.
        // the dataGrid passes it to the currentRow. if it is anything other 
        // than Enter or TAB, the currentRow resets the FocusedRelation variable.
        // 
        // Then the dataGrid takes another look at the TAB key and if it is the case 
        // it passes it to the row. If the dataRelationshipRow can become focused,
        // then it eats the TAB key, otherwise it will give it back to the dataGrid. 
        //
        internal override bool ProcessTabKey(Keys keyData, Rectangle rowHeaders, bool alignToRight) {
            Debug.Assert((keyData & Keys.Control) != Keys.Control, "the DataGridRelationshipRow only handles TAB and TAB-SHIFT");
            Debug.Assert((keyData & Keys.Alt) != Keys.Alt, "the DataGridRelationshipRow only handles TAB and TAB-SHIFT"); 

            // if there are no relationships, this row can't do anything with the 
            // key 
            if (this.dgTable.RelationsList.Count == 0 || dgTable.DataGrid == null || !dgTable.DataGrid.AllowNavigation)
                return false; 

            // expand the relationship box
            if (!expanded)
                Expand(); 

            if ((keyData & Keys.Shift) == Keys.Shift) { 
                if (FocusedRelation == 0) { 
                    // if user hits TAB-SHIFT and the focus was on the first relationship then
                    // reset FocusedRelation and let the dataGrid use the key 
                    //
                    // consider: [....]: if the relationships box is expanded, should we collapse it on leave?
                    FocusedRelation = -1;
                    return false; 
                }
 
                // we need to invalidate the relationshipRectangle, and cause the linkFont to move 
                // to the next relation
                Rectangle relRect = GetRelationshipRect(); 
                relRect.X += rowHeaders.X + this.dgTable.RowHeaderWidth;
                relRect.X = MirrorRelationshipRectangle(relRect, rowHeaders, alignToRight);
                InvalidateRowRect(relRect);
 
                if (FocusedRelation == -1)
                    // is the first time that the user focuses on this 
                    // set of relationships 
                    FocusedRelation = this.dgTable.RelationsList.Count - 1;
                else 
                    FocusedRelation --;
                return true;
            }
            else { 
                if (FocusedRelation == this.dgTable.RelationsList.Count - 1) {
                    // if the user hits TAB and the focus was on the last relationship then 
                    // reset FocusedRelation and let the dataGrid use the key 
                    //
                    // consider: [....]: if the relationships box is expanded, should we collapse it on leave? 
                    FocusedRelation = -1;
                    return false;
                }
 
                // we need to invalidate the relationshipRectangle, and cause the linkFont to move
                // to the next relation 
                Rectangle relRect = GetRelationshipRect(); 
                relRect.X += rowHeaders.X + this.dgTable.RowHeaderWidth;
                relRect.X = MirrorRelationshipRectangle(relRect, rowHeaders, alignToRight); 
                InvalidateRowRect(relRect);

                FocusedRelation ++;
                return true; 
            }
        } 
 
        /// 
        ///  
        ///      Paints the row.
        /// 
        public override int Paint(Graphics g, Rectangle bounds, Rectangle trueRowBounds, int firstVisibleColumn, int numVisibleColumns) {
            return Paint(g, bounds, trueRowBounds, firstVisibleColumn, numVisibleColumns, false); 
        }
 
        public override int Paint(Graphics g, 
                                  Rectangle bounds,          // negative offsetted row bounds
                                  Rectangle trueRowBounds,   // real row bounds. 
                                  int firstVisibleColumn,
                                  int numVisibleColumns,
                                  bool alignToRight) {
            if (CompModSwitches.DGRelationShpRowPaint.TraceVerbose) Debug.WriteLine("Painting row " + RowNumber.ToString(CultureInfo.InvariantCulture) + " with bounds " + bounds.ToString()); 
            int bWidth = this.dgTable.BorderWidth;
 
            // paint the data cells 
            Rectangle dataBounds = bounds;
            dataBounds.Height = base.Height - bWidth; 
            int dataWidth = PaintData(g, dataBounds, firstVisibleColumn, numVisibleColumns, alignToRight);
            int dataWidthOffsetted = dataWidth + bounds.X - trueRowBounds.X;

            dataBounds.Offset(0, bWidth);       // use bWidth, not 1 
            if (bWidth > 0)
                PaintBottomBorder(g, dataBounds, dataWidth, bWidth, alignToRight); 
 
            if (expanded && this.dgTable.RelationsList.Count > 0) {
                // paint the relationships 
                Rectangle relationBounds = new Rectangle(trueRowBounds.X,
                                                         dataBounds.Bottom,
                                                         trueRowBounds.Width,
                                                         trueRowBounds.Height - dataBounds.Height - 2 * bWidth); 
                PaintRelations(g, relationBounds, trueRowBounds, dataWidthOffsetted,
                               firstVisibleColumn, numVisibleColumns, alignToRight); 
                relationBounds.Height += 1; 
                if (bWidth > 0)
                    PaintBottomBorder(g, relationBounds, dataWidthOffsetted, bWidth, alignToRight); 
            }

            return dataWidth;
        } 

        protected override void PaintCellContents(Graphics g, Rectangle cellBounds, DataGridColumnStyle column, 
                                                  Brush backBr, Brush foreBrush, bool alignToRight) { 
            CurrencyManager listManager = DataGrid.ListManager;
 
            // painting the error..
            //
            string errString = String.Empty;
            Rectangle bounds = cellBounds; 
            object errInfo = DataGrid.ListManager[this.number];
            if (errInfo is IDataErrorInfo) 
                errString = ((IDataErrorInfo) errInfo)[column.PropertyDescriptor.Name]; 

            if (!String.IsNullOrEmpty(errString)) { 
                Bitmap bmp = GetErrorBitmap();
                Rectangle errRect;
                lock (bmp) {
                    errRect = PaintIcon(g, bounds, true, alignToRight, bmp, backBr); 
                }
                // paint the errors correctly when RTL = true 
                if (alignToRight) 
                    bounds.Width -= errRect.Width + xOffset;
                else 
                    bounds.X += errRect.Width + xOffset;
                DataGrid.ToolTipProvider.AddToolTip(errString, (IntPtr)(DataGrid.ToolTipId ++), errRect);
            }
 
            column.Paint(g, bounds, listManager, this.RowNumber, backBr, foreBrush, alignToRight);
        } 
 
        public override void PaintHeader(Graphics g, Rectangle bounds, bool alignToRight, bool isDirty) {
 
            DataGrid grid = this.DataGrid;

            Rectangle insideBounds = bounds;
 
            if (!grid.FlatMode) {
                ControlPaint.DrawBorder3D(g, insideBounds, Border3DStyle.RaisedInner); 
                insideBounds.Inflate(-1,-1); 
            }
 
            if (this.dgTable.IsDefault)
                PaintHeaderInside(g, insideBounds, this.DataGrid.HeaderBackBrush, alignToRight, isDirty);
            else
                PaintHeaderInside(g, insideBounds, this.dgTable.HeaderBackBrush, alignToRight, isDirty); 
        }
 
        public void PaintHeaderInside(Graphics g, Rectangle bounds, Brush backBr, bool alignToRight, bool isDirty) { 
            // paint the row header
            bool paintPlusMinus = dgTable.RelationsList.Count > 0 && dgTable.DataGrid.AllowNavigation; 
            int rowHeaderBoundsX = MirrorRectangle(bounds.X,
                                                   bounds.Width - (paintPlusMinus ? expandoBoxWidth : 0),
                                                   bounds, alignToRight);
 
            if (!alignToRight) Debug.Assert(bounds.X == rowHeaderBoundsX, "what's up doc?");
 
            Rectangle rowHeaderBounds = new Rectangle(rowHeaderBoundsX, 
                                                      bounds.Y,
                                                      bounds.Width - (paintPlusMinus ? expandoBoxWidth : 0), 
                                                      bounds.Height);

            base.PaintHeader(g, rowHeaderBounds, alignToRight, isDirty);
 
            // Paint the expando on the right
            int expandoBoxX = MirrorRectangle(bounds.X + rowHeaderBounds.Width, expandoBoxWidth, bounds, alignToRight); 
 
            if (!alignToRight) Debug.Assert(rowHeaderBounds.Right == expandoBoxX, "what's up doc?");
 
            Rectangle expandoBox = new Rectangle(expandoBoxX,
                                                 bounds.Y,
                                                 expandoBoxWidth,
                                                 bounds.Height); 
            if (paintPlusMinus) {
                PaintPlusMinusGlyph(g, expandoBox, backBr, alignToRight); 
            } 

        } 

        /// 
        /// 
        ///      Paints the relationships below the data area. 
        /// 
        private void PaintRelations(Graphics g, Rectangle bounds, Rectangle trueRowBounds, 
                                    int dataWidth, int firstCol, int nCols, bool alignToRight) { 

            // Calculate the relationship rect. 
            // relationshipRect = Rectangle.Empty;
            Rectangle relRect = GetRelationshipRect();
            //relRect.Offset(trueRowBounds.X, trueRowBounds.Y);
            relRect.X = alignToRight ? bounds.Right - relRect.Width : bounds.X; 
            relRect.Y = bounds.Y;
            int paintedWidth = Math.Max(dataWidth, relRect.Width); 
 
            // Paint the stuff to the right , or left (Bi-Di) of the relationship rect.
            Region r = g.Clip; 
            g.ExcludeClip(relRect);

            g.FillRectangle(GetBackBrush(),
                            alignToRight ? bounds.Right - dataWidth : bounds.X, 
                            bounds.Y,
                            dataWidth, 
                            bounds.Height); 

            // Paint the relations' text 
            g.SetClip(bounds);

            relRect.Height -= this.dgTable.BorderWidth;     // use bWidth not 1
            g.DrawRectangle(SystemPens.ControlText, relRect.X, relRect.Y, relRect.Width - 1, relRect.Height - 1); 
            relRect.Inflate(-1, -1);
 
            int cy = PaintRelationText(g, relRect, alignToRight); 

            if (cy < relRect.Height) { 
                g.FillRectangle(GetBackBrush(), relRect.X, relRect.Y + cy, relRect.Width, relRect.Height - cy);
            }

            g.Clip = r; 

            // paint any exposed area to the right or to the left (BI-DI) 
            if (paintedWidth < bounds.Width) { 
                int bWidth;
                if (this.dgTable.IsDefault) 
                    bWidth = this.DataGrid.GridLineWidth;
                else
                    bWidth = this.dgTable.GridLineWidth;
                g.FillRectangle(DataGrid.BackgroundBrush, 
                                alignToRight ? bounds.X : bounds.X + paintedWidth,
                                bounds.Y, 
                                bounds.Width - paintedWidth - bWidth + 1, // + 1 cause the relationship rectangle was deflated 
                                bounds.Height);
 
                // Paint the border to the right of each cell
                if (bWidth > 0) {
                    Brush br;
                    // if the user changed the gridLineColor on the dataGrid 
                    // from the defaultValue, then use that value;
                    if (this.dgTable.IsDefault) 
                        br = this.DataGrid.GridLineBrush; 
                    else
                        br = this.dgTable.GridLineBrush; 
                    g.FillRectangle(br,
                                    alignToRight ? bounds.Right - bWidth - paintedWidth : bounds.X + paintedWidth - bWidth,
                                    bounds.Y,
                                    bWidth, 
                                    bounds.Height);
                } 
            } 

        } 

        private int PaintRelationText(Graphics g, Rectangle bounds, bool alignToRight) {
            g.FillRectangle(GetBackBrush(), bounds.X, bounds.Y, bounds.Width, System.Windows.Forms.DataGridTableStyle.relationshipSpacing);
 
            int relationshipHeight = this.dgTable.RelationshipHeight;
            Rectangle textBounds = new Rectangle(bounds.X, bounds.Y + System.Windows.Forms.DataGridTableStyle.relationshipSpacing, 
                                                 bounds.Width, 
                                                 relationshipHeight);
            int cy = System.Windows.Forms.DataGridTableStyle.relationshipSpacing; 
            for (int r = 0; r < this.dgTable.RelationsList.Count; ++r) {
                if (cy > bounds.Height)
                    break;
 
                Brush textBrush = this.dgTable.IsDefault ? this.DataGrid.LinkBrush : this.dgTable.LinkBrush;
 
                Font textFont = this.DataGrid.Font; 
                textBrush = this.dgTable.IsDefault ? this.DataGrid.LinkBrush : this.dgTable.LinkBrush;
                textFont = this.DataGrid.LinkFont; 

                g.FillRectangle(GetBackBrush(), textBounds);

                StringFormat format = new StringFormat(); 
                if (alignToRight) {
                    format.FormatFlags |= StringFormatFlags.DirectionRightToLeft; 
                    format.Alignment = StringAlignment.Far; 
                }
                g.DrawString(((string)this.dgTable.RelationsList[r]), textFont, textBrush, textBounds, 
                             format);
                if (r == FocusedRelation && this.number == this.DataGrid.CurrentCell.RowNumber) {
                    textBounds.Width = this.dgTable.FocusedTextWidth;
                    ControlPaint.DrawFocusRectangle(g, textBounds, ((SolidBrush)textBrush).Color, ((SolidBrush)GetBackBrush()).Color); 
                    textBounds.Width = bounds.Width;
                } 
                format.Dispose(); 

                textBounds.Y += relationshipHeight; 
                cy += textBounds.Height;
            }
            return cy;
        } 

        ///  
        ///  
        private void PaintPlusMinusGlyph(Graphics g, Rectangle bounds, Brush backBr, bool alignToRight) {
            if (CompModSwitches.DGRelationShpRowPaint.TraceVerbose) Debug.WriteLine("PlusMinusGlyph painting in bounds    -> " + bounds.ToString()); 
            Rectangle outline = GetOutlineRect(bounds.X, bounds.Y);

            outline = Rectangle.Intersect(bounds, outline);
            if (outline.IsEmpty) 
                return;
 
            g.FillRectangle(backBr, bounds); 

            if (CompModSwitches.DGRelationShpRowPaint.TraceVerbose) Debug.WriteLine("Painting PlusMinusGlyph with outline -> " + outline.ToString()); 
            // draw the +/- box
            Pen drawPen = this.dgTable.IsDefault ? this.DataGrid.HeaderForePen : this.dgTable.HeaderForePen;
            g.DrawRectangle(drawPen, outline.X, outline.Y, outline.Width - 1, outline.Height - 1);
 
            int indent = 2;
            // draw the - 
            g.DrawLine(drawPen, 
                       outline.X + indent, outline.Y + outline.Width / 2,
                       outline.Right - indent - 1, outline.Y + outline.Width/2);        // -1 on the y coordinate 

            if (!expanded) {
                // draw the vertical line to make +
                g.DrawLine(drawPen, 
                           outline.X + outline.Height/2, outline.Y + indent,
                           outline.X + outline.Height/2, outline.Bottom - indent - 1); // -1... hinting 
            } 
            else {
                Point[] points = new Point[3]; 
                points[0] = new Point(outline.X + outline.Height/2, outline.Bottom);

                points[1] = new Point(points[0].X, bounds.Y + 2*indent + base.Height);
 
                points[2] = new Point(alignToRight ? bounds.X : bounds.Right,
                                      points[1].Y); 
                g.DrawLines(drawPen, points); 
            }
        } 

        private int RelationFromY(int y) {
            int relation = -1;
            int relationshipHeight = this.dgTable.RelationshipHeight; 
            Rectangle relRect = GetRelationshipRect();
            int cy = base.Height - this.dgTable.BorderWidth + System.Windows.Forms.DataGridTableStyle.relationshipSpacing; 
            while (cy < relRect.Bottom) { 
                if (cy > y)
                    break; 
                cy += relationshipHeight;
                relation++;
            }
            if (relation >= this.dgTable.RelationsList.Count) 
                return -1;
            return relation; 
        } 

        // given the relRect and the rowHeader, this function will return the 
        // X coordinate of the relationship rectangle as it should appear on the screen
        private int MirrorRelationshipRectangle(Rectangle relRect, Rectangle rowHeader, bool alignToRight) {
            if (alignToRight)
                return rowHeader.X - relRect.Width; 
            else
                return relRect.X; 
 
        }
 
        // given the X and Width of a rectangle R1 contained in rect,
        // this will return the X coordinate of the rectangle that corresponds to R1 in Bi-Di transformation
        private int MirrorRectangle(int x, int width, Rectangle rect, bool alignToRight) {
            if (alignToRight) 
                return rect.Right + rect.X - width - x;
            else 
                return x; 
        }
 
        [ComVisible(true)]
        protected class DataGridRelationshipRowAccessibleObject : DataGridRowAccessibleObject {
            public DataGridRelationshipRowAccessibleObject(DataGridRow owner) : base(owner) {
            } 

 
            protected override void AddChildAccessibleObjects(IList children) { 
                base.AddChildAccessibleObjects(children);
                DataGridRelationshipRow row = (DataGridRelationshipRow)Owner; 
                if (row.dgTable.RelationsList!= null) {
                    for (int i=0; i 0) { 
                        if (Row.Expanded) {
                            return SR.GetString(SR.AccDGCollapse); 
                        }
                        else {
                            return SR.GetString(SR.AccDGExpand);
                        } 
                    }
                    return null; 
                } 
            }
 
            public override AccessibleStates State {
                get {
                    AccessibleStates state = base.State;
                    if (Row.dgTable.RelationsList.Count > 0) { 
                        if (((DataGridRelationshipRow)Owner).Expanded) {
                            state |= AccessibleStates.Expanded; 
                        } 
                        else {
                            state |= AccessibleStates.Collapsed; 
                        }
                    }
                    return state;
                } 
            }
 
            [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] 
            public override void DoDefaultAction() {
                if (Row.dgTable.RelationsList.Count > 0) { 
                    ((DataGridRelationshipRow)Owner).Expanded = !((DataGridRelationshipRow)Owner).Expanded;
                }
            }
 
            public override AccessibleObject GetFocused() {
                DataGridRelationshipRow row = (DataGridRelationshipRow)Owner; 
                int focusRel = row.dgTable.FocusedRelation; 
                if (focusRel == -1) {
                    return base.GetFocused(); 
                }
                else {
                    return GetChild(GetChildCount() - row.dgTable.RelationsList.Count + focusRel);
                } 
            }
        } 
 
        [ComVisible(true)]
        protected class DataGridRelationshipAccessibleObject : AccessibleObject { 
            DataGridRelationshipRow owner = null;
            int relationship;

            public DataGridRelationshipAccessibleObject(DataGridRelationshipRow owner, int relationship) : base() { 
                Debug.Assert(owner != null, "DataGridRelationshipAccessibleObject must have a valid owner DataGridRow");
                this.owner = owner; 
                this.relationship = relationship; 
            }
 
            public override Rectangle Bounds {
                get {
                    Rectangle rowBounds = DataGrid.GetRowBounds(owner);
 
                    Rectangle bounds = owner.Expanded ? owner.GetRelationshipRectWithMirroring() : Rectangle.Empty;
                    bounds.Y += owner.dgTable.RelationshipHeight * relationship; 
                    bounds.Height = owner.Expanded ? owner.dgTable.RelationshipHeight : 0;      // when the row is collapsed the height of the relationship object should be 0 
                    // GetRelationshipRectWithMirroring will use the row headers width
                    if (!owner.Expanded) 
                        bounds.X += rowBounds.X;
                    bounds.Y += rowBounds.Y;

                    return owner.DataGrid.RectangleToScreen(bounds); 
                }
            } 
 
            public override string Name {
                get { 
                    return (string)owner.dgTable.RelationsList[relationship];
                }
            }
 
            protected DataGridRelationshipRow Owner {
                get { 
                    return owner; 
                }
            } 

            public override AccessibleObject Parent {
                [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
                get { 
                    return owner.AccessibleObject;
                } 
            } 

            protected DataGrid DataGrid { 
                get {
                    return owner.DataGrid;
                }
            } 

            public override AccessibleRole Role { 
                get { 
                    return AccessibleRole.Link;
                } 
            }

            public override AccessibleStates State {
                get { 

                    DataGridRow[] dgRows = this.DataGrid.DataGridRows; 
                    if (Array.IndexOf(dgRows, this.owner) == -1) { 
                        return AccessibleStates.Unavailable;
                    } 

                    AccessibleStates state = AccessibleStates.Selectable
                        | AccessibleStates.Focusable
                        | AccessibleStates.Linked; 

                    if (!owner.Expanded) { 
                        state |= AccessibleStates.Invisible; 
                    }
 
                    if (DataGrid.Focused && Owner.dgTable.FocusedRelation == relationship) {
                        state |= AccessibleStates.Focused;
                    }
 
                    return state;
                } 
            } 

            public override string Value { 
                get {
                    DataGridRow[] dgRows = this.DataGrid.DataGridRows;
                    if (Array.IndexOf(dgRows, this.owner) == -1) {
                        return null; 
                    } else {
                        return (string)owner.dgTable.RelationsList[relationship]; 
                    } 
                }
                set { 
                    // not supported
                }
            }
 
            public override string DefaultAction {
                get { 
                    return SR.GetString(SR.AccDGNavigate); 
                }
            } 

            [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
            public override void DoDefaultAction() {
                ((DataGridRelationshipRow)Owner).Expanded = true; 
                owner.FocusedRelation = -1;
                DataGrid.NavigateTo((string)owner.dgTable.RelationsList[relationship], owner, true); 
                DataGrid.BeginInvoke(new MethodInvoker(this.ResetAccessibilityLayer)); 
            }
 
            private void ResetAccessibilityLayer() {
                ((DataGrid.DataGridAccessibleObject) DataGrid.AccessibilityObject).NotifyClients(AccessibleEvents.Reorder, 0);
                ((DataGrid.DataGridAccessibleObject) DataGrid.AccessibilityObject).NotifyClients(AccessibleEvents.Focus, DataGrid.CurrentCellAccIndex);
                ((DataGrid.DataGridAccessibleObject) DataGrid.AccessibilityObject).NotifyClients(AccessibleEvents.Selection, DataGrid.CurrentCellAccIndex); 
            }
 
            ///  
            /// 
            ///      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: 
                        if (relationship + 1 < owner.dgTable.RelationsList.Count) {
                            return Parent.GetChild(Parent.GetChildCount() - owner.dgTable.RelationsList.Count + relationship + 1); 
                        }
                        break;
                    case AccessibleNavigation.Up:
                    case AccessibleNavigation.Left: 
                    case AccessibleNavigation.Previous:
                        if (relationship > 0) { 
                            return Parent.GetChild(Parent.GetChildCount() - owner.dgTable.RelationsList.Count + relationship - 1); 
                        }
                        break; 
                }

                return null;
 
            }
 
            [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] 
            public override void Select(AccessibleSelection flags) {
                // Focus the PropertyGridView window 
                //
                if ( (flags & AccessibleSelection.TakeFocus) == AccessibleSelection.TakeFocus) {
                    DataGrid.Focus();
                } 

                if ( (flags & AccessibleSelection.TakeSelection) == AccessibleSelection.TakeSelection) { 
                    Owner.FocusedRelation = relationship; 
                }
            } 

        }

    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

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