/// <summary>
 ///     Compare two VirtualTreeItemInfo structures
 /// </summary>
 /// <param name="operand1">Left operand</param>
 /// <param name="operand2">Right operand</param>
 /// <returns>true if operands are equal</returns>
 public static bool Compare(VirtualTreeItemInfo operand1, VirtualTreeItemInfo operand2)
 {
     return operand1.myBranch == operand2.myBranch && operand1.myColumn == operand2.myColumn && operand1.myRow == operand2.myRow
            && operand1.myLevel == operand2.myLevel && operand1.myFlags == operand2.myFlags;
 }
 private int ListItemStringWidth(Graphics graphics, Font font, ref VirtualTreeItemInfo info)
 {
     return ListItemStringWidth(graphics, font, info.Branch.GetText(info.Row, info.Column));
 }
        private int ComputeWidthOfRange(int column, int startIndex, int count, out int firstMax, out int lastMax)
        {
            firstMax = VirtualTreeConstant.NullIndex;
            lastMax = VirtualTreeConstant.NullIndex;
            if (count == 0)
            {
                return 0;
            }
            var maxWidth = 1;

            Debug.Assert(count < 0x10000000); //Something is wrong with the count of visible items. Defaulting to 1
            if (count >= 0x10000000)
            {
                count = 1;
            }

            using (var g = CreateGraphics())
            {
                var columnItems = myTree.EnumerateColumnItems(column, null, false, startIndex, startIndex + count - 1);
                var styleLevelAdjust = GetAnyStyleFlag(VTCStyleFlags.HasRootLines | VTCStyleFlags.HasRootButtons);
                var levelAdjust = 0;
                var lastLevel = -1;
                var lastIsSimple = false;
                int curWidth;
                int imageWidth;
                var baseOffset = 0;
                while (columnItems.MoveNext())
                {
                    if (lastLevel != columnItems.Level
                        || lastIsSimple != columnItems.SimpleCell)
                    {
                        lastIsSimple = columnItems.SimpleCell;
                        lastLevel = columnItems.Level;
                        if (styleLevelAdjust)
                        {
                            levelAdjust = (columnItems.ColumnInTree == 0 || !columnItems.SimpleCell) ? 1 : 0;
                        }
                        baseOffset = (lastLevel + levelAdjust) * myIndentWidth;
                    }
                    var info = new VirtualTreeItemInfo(columnItems.Branch, columnItems.RowInBranch, columnItems.ColumnInBranch, 0);
                    curWidth = ListItemStringWidth(g, ref info, out imageWidth);
                    curWidth += baseOffset + imageWidth;
                    if (maxWidth == curWidth)
                    {
                        lastMax = columnItems.RowInTree;
                    }
                    else if (maxWidth < curWidth)
                    {
                        maxWidth = curWidth;
                        firstMax = lastMax = columnItems.RowInTree;
                    }
                }
            } // using g

            return maxWidth;
        }
 private int ListItemStringWidth(ref VirtualTreeItemInfo info, string alternateText, out int imageWidth)
 {
     using (var g = CreateGraphics())
     {
         return ListItemStringWidth(
             g,
             ref info,
             alternateText,
             out imageWidth);
     }
 }
 /// <summary>
 ///     Use this override if the font has already been determined via GetDisplayData
 /// </summary>
 /// <param name="font"></param>
 /// <param name="info"></param>
 /// <returns></returns>
 private int ListItemStringWidth(Font font, ref VirtualTreeItemInfo info)
 {
     using (var g = CreateGraphics())
     {
         return ListItemStringWidth(
             g,
             font,
             ref info);
     }
 }
 private string FormatReplacementFields(
     int row, int column, ref VirtualTreeItemInfo info, string formatString, AccessibilityReplacementField[] replacementFields,
     string[] imageDescriptions, string[] stateImageDescriptions)
 {
     var replacementCount = replacementFields.Length;
     var displayData = VirtualTreeDisplayData.Empty;
     var haveDisplayData = false;
     var fields = new string[replacementCount];
     var branch = info.Branch;
     var locRow = info.Row;
     var locCol = info.Column;
     StringBuilder builder = null;
     AccessibilityReplacementField curField;
     var culture = CultureInfo.CurrentUICulture;
     for (var i = 0; i < replacementCount; ++i)
     {
         curField = replacementFields[i];
         switch (curField)
         {
             case AccessibilityReplacementField.ColumnHeader:
                 if (myHeaderBounds.HasHeaders)
                 {
                     fields[i] = myHeaderBounds.Headers[column].Text;
                 }
                 break;
             case AccessibilityReplacementField.GlobalRow0:
                 fields[i] = row.ToString(culture);
                 break;
             case AccessibilityReplacementField.GlobalRow1:
                 fields[i] = (row + 1).ToString(culture);
                 break;
             case AccessibilityReplacementField.GlobalRowText0:
                 fields[i] = string.Format(culture, VirtualTreeStrings.GetString(VirtualTreeStrings.RowAccDesc), row);
                 break;
             case AccessibilityReplacementField.GlobalRowText1:
                 fields[i] = string.Format(culture, VirtualTreeStrings.GetString(VirtualTreeStrings.RowAccDesc), row + 1);
                 break;
             case AccessibilityReplacementField.GlobalColumn0:
                 fields[i] = column.ToString(culture);
                 break;
             case AccessibilityReplacementField.GlobalColumn1:
                 fields[i] = (column + 1).ToString(culture);
                 break;
             case AccessibilityReplacementField.GlobalColumnText0:
                 fields[i] = string.Format(culture, VirtualTreeStrings.GetString(VirtualTreeStrings.ColumnAccDesc), column);
                 break;
             case AccessibilityReplacementField.GlobalColumnText1:
                 fields[i] = string.Format(culture, VirtualTreeStrings.GetString(VirtualTreeStrings.RowAccDesc), column + 1);
                 break;
             case AccessibilityReplacementField.GlobalRowAndColumnText0:
                 fields[i] = string.Format(culture, VirtualTreeStrings.GetString(VirtualTreeStrings.RowColumnAccDesc), row, column);
                 break;
             case AccessibilityReplacementField.GlobalRowAndColumnText1:
                 fields[i] = string.Format(
                     culture, VirtualTreeStrings.GetString(VirtualTreeStrings.RowColumnAccDesc), row + 1, column + 1);
                 break;
             case AccessibilityReplacementField.LocalRow0:
                 fields[i] = locRow.ToString(culture);
                 break;
             case AccessibilityReplacementField.LocalRow1:
                 fields[i] = (locRow + 1).ToString(culture);
                 break;
             case AccessibilityReplacementField.LocalRowText0:
                 fields[i] = string.Format(culture, VirtualTreeStrings.GetString(VirtualTreeStrings.RowAccDesc), locRow);
                 break;
             case AccessibilityReplacementField.LocalRowText1:
                 fields[i] = string.Format(culture, VirtualTreeStrings.GetString(VirtualTreeStrings.RowAccDesc), locRow + 1);
                 break;
             case AccessibilityReplacementField.LocalRowOfTotal:
                 fields[i] = string.Format(
                     culture, VirtualTreeStrings.GetString(VirtualTreeStrings.RowOfTotalAccDesc), locRow + 1, branch.VisibleItemCount);
                 break;
             case AccessibilityReplacementField.ChildRowCount:
             case AccessibilityReplacementField.ChildRowCountText:
                 {
                     var descendantCount = Tree.GetDescendantItemCount(row, column, false, false);
                     if (curField == AccessibilityReplacementField.ChildRowCountText)
                     {
                         fields[i] = string.Format(
                             culture, VirtualTreeStrings.GetString(VirtualTreeStrings.ChildRowNumberAccDesc), descendantCount);
                     }
                     else
                     {
                         fields[i] = descendantCount.ToString(culture);
                     }
                     break;
                 }
             case AccessibilityReplacementField.ColumnCount:
             case AccessibilityReplacementField.ColumnCountText:
                 {
                     var columnCount = 1;
                     if (myMctree != null)
                     {
                         var mcBranch = branch as IMultiColumnBranch;
                         if (mcBranch != null)
                         {
                             // UNDONE: Column Permutation
                             columnCount = Math.Min(
                                 myMctree.ColumnCount,
                                 (0 != (branch.Features & BranchFeatures.JaggedColumns))
                                     ? mcBranch.ColumnCount
                                     : mcBranch.GetJaggedColumnCount(locRow));
                         }
                     }
                     if (curField == AccessibilityReplacementField.ColumnCountText)
                     {
                         fields[i] = string.Format(
                             culture, VirtualTreeStrings.GetString(VirtualTreeStrings.ColumnNumberAccDesc), columnCount);
                     }
                     else
                     {
                         fields[i] = columnCount.ToString(culture);
                     }
                     break;
                 }
             case AccessibilityReplacementField.DisplayText:
                 fields[i] = branch.GetText(locRow, locCol);
                 break;
             case AccessibilityReplacementField.ImageTipText:
                 fields[i] = branch.GetTipText(locRow, locCol, ToolTipType.Icon);
                 break;
             case AccessibilityReplacementField.PrimaryImageText:
             case AccessibilityReplacementField.PrimaryImageAndOverlaysText:
             case AccessibilityReplacementField.StateImageText:
                 {
                     if (!haveDisplayData)
                     {
                         displayData = branch.GetDisplayData(
                             locRow, locCol,
                             new VirtualTreeDisplayDataMasks(
                                 VirtualTreeDisplayMasks.Image | VirtualTreeDisplayMasks.ImageOverlays
                                 | VirtualTreeDisplayMasks.StateImage, 0));
                     }
                     string[] descriptions;
                     int imageIndex;
                     int descriptionsLength;
                     switch (curField)
                     {
                         case AccessibilityReplacementField.PrimaryImageAndOverlaysText:
                         case AccessibilityReplacementField.PrimaryImageText:
                             imageIndex = displayData.Image;
                             if (imageIndex >= 0)
                             {
                                 descriptions = (displayData.ImageList == null) ? myImageDescriptions : imageDescriptions;
                                 if (descriptions != null)
                                 {
                                     descriptionsLength = descriptions.Length;
                                     if (imageIndex < descriptionsLength)
                                     {
                                         fields[i] = descriptions[imageIndex];
                                     }
                                     if (curField == AccessibilityReplacementField.PrimaryImageAndOverlaysText)
                                     {
                                         imageIndex = displayData.OverlayIndex;
                                         if (imageIndex != -1)
                                         {
                                             var separator = culture.TextInfo.ListSeparator;
                                             var overlayIndices = displayData.OverlayIndices;
                                             if (overlayIndices == null)
                                             {
                                                 if (imageIndex < descriptionsLength)
                                                 {
                                                     fields[i] = string.Concat(fields[i], separator, descriptions[imageIndex]);
                                                 }
                                             }
                                             else
                                             {
                                                 if (builder == null)
                                                 {
                                                     builder = new StringBuilder();
                                                 }
                                                 else
                                                 {
                                                     builder.Length = 0;
                                                 }
                                                 var startString = fields[i];
                                                 if (startString != null
                                                     && startString.Length != 0)
                                                 {
                                                     builder.Append(fields[i]);
                                                 }
                                                 else
                                                 {
                                                     // Keep track of this value so we can rip the leading
                                                     // separator later if the primary image had no text
                                                     startString = null;
                                                 }
                                                 // Use the index as a list of bits into the indices array.
                                                 // Do this typed if possible. It returns an IList to be CLS
                                                 // compliant. Note that this differs from the drawing routines
                                                 // for the images, which draw backwards, while this contatenates forwards.
                                                 int[] indicesArray;
                                                 IList<int> typedList;
                                                 var overlayIndex = imageIndex;
                                                 int indicesCount;
                                                 int curIndex;
                                                 int curBit;
                                                 indicesCount = overlayIndices.Count;
                                                 curBit = 1;
                                                 if (null != (indicesArray = overlayIndices as int[]))
                                                 {
                                                     for (curIndex = 0; curIndex < indicesCount; ++curIndex)
                                                     {
                                                         if (0 != (curBit & overlayIndex))
                                                         {
                                                             imageIndex = indicesArray[curIndex];
                                                             if (imageIndex < descriptionsLength)
                                                             {
                                                                 builder.Append(separator);
                                                                 builder.Append(descriptions[imageIndex]);
                                                             }
                                                         }
                                                         curBit <<= 1;
                                                     }
                                                 }
                                                 else if (null != (typedList = overlayIndices as IList<int>))
                                                 {
                                                     for (curIndex = 0; curIndex < indicesCount; ++curIndex)
                                                     {
                                                         if (0 != (curBit & overlayIndex))
                                                         {
                                                             imageIndex = typedList[curIndex];
                                                             if (imageIndex < descriptionsLength)
                                                             {
                                                                 builder.Append(separator);
                                                                 builder.Append(descriptions[imageIndex]);
                                                             }
                                                         }
                                                         curBit <<= 1;
                                                     }
                                                 }
                                                 else
                                                 {
                                                     for (curIndex = 0; curIndex < indicesCount; ++curIndex)
                                                     {
                                                         if (0 != (curBit & overlayIndex))
                                                         {
                                                             imageIndex = (int)overlayIndices[curIndex];
                                                             if (imageIndex < descriptionsLength)
                                                             {
                                                                 builder.Append(separator);
                                                                 builder.Append(descriptions[imageIndex]);
                                                             }
                                                         }
                                                         curBit <<= 1;
                                                     }
                                                 }
                                                 if (startString == null)
                                                 {
                                                     // Strip leading separator if we had nothing to start with
                                                     var separatorLength = separator.Length;
                                                     fields[i] = builder.ToString(separatorLength, builder.Length - separatorLength);
                                                 }
                                                 else
                                                 {
                                                     fields[i] = builder.ToString();
                                                 }
                                             }
                                         }
                                     }
                                 }
                             }
                             break;
                         case AccessibilityReplacementField.StateImageText:
                             if (displayData.StateImageIndex >= 0)
                             {
                                 descriptions = (displayData.StateImageList == null)
                                                    ? myStateImageDescriptions
                                                    : stateImageDescriptions;
                                 if (descriptions != null
                                     && displayData.StateImageIndex < descriptions.Length)
                                 {
                                     fields[i] = descriptions[displayData.StateImageIndex];
                                 }
                             }
                             break;
                     }
                 }
                 break;
         }
     }
     return string.Format(culture, formatString, fields);
 }
        private int ListItemStringWidth(Graphics graphics, ref VirtualTreeItemInfo info, string alternateText, out int imageWidth)
        {
            imageWidth = 0;
            var tddMasks = new VirtualTreeDisplayDataMasks(VirtualTreeDisplayMasks.State, VirtualTreeDisplayStates.Bold);
            var fCheckImage = myImageWidth > 0;
            var fCheckState = myStateImageWidth > 0;
            if (fCheckImage)
            {
                tddMasks.Mask |= VirtualTreeDisplayMasks.Image;
            }
            if (fCheckState)
            {
                tddMasks.Mask |= VirtualTreeDisplayMasks.StateImage;
            }
            var tdd = info.Branch.GetDisplayData(info.Row, info.Column, tddMasks);
            var font = (0 == (tdd.State & VirtualTreeDisplayStates.Bold)) ? Font : BoldFont;

            int retVal;
            if (alternateText == null)
            {
                retVal = ListItemStringWidth(
                    graphics,
                    font,
                    ref info);
            }
            else
            {
                retVal = ListItemStringWidth(
                    graphics,
                    font,
                    alternateText);
            }
            if (fCheckImage && tdd.Image != -1)
            {
                imageWidth += myImageWidth;
            }
            if (fCheckState && tdd.StateImageIndex >= 0)
            {
                imageWidth += myStateImageWidth;
            }
            return retVal;
        }
            // row and column here are the row and column of the parent item.
            // The local column (relative to the parent branch) can be retrieved from the VirtualTreeItemInfo.
            public AccColumn(
                VirtualTreeControl ctl, int row, int displayColumn, int nativeColumn, AccItemSettings settings, ref VirtualTreeItemInfo info)
            {
                // Blank row is calculated explicitly, ignore it if it is passed in
                settings = (AccItemSettings)((int)settings & ~(int)(AccItemSettings.BlankRow));
                myCtl = ctl;
                var tree = ctl.Tree;
                var lastRowAdjust = 0;
                if (info.Column == 0)
                {
                    // Looking at a complex column
                    myChildCount = info.Branch.VisibleItemCount;
                    lastRowAdjust = -1;
                }
                else
                {
                    // This is a wrapper around a single-celled column. It can
                    // only have one item in it. Flag with a -1 to distinguish it
                    // from a complex column
                    myChildCount = -1;
                }

                // Expand column to include blanks to the bottom and right
                var expansion =
                    tree.GetBlankExpansion(
                        row + lastRowAdjust + tree.GetDescendantItemCount(row, nativeColumn, true, myChildCount != -1), displayColumn,
                        myCtl.myColumnPermutation);
                myRow = row;
                myRowHeight = expansion.BottomRow - row + 1;
                displayColumn = expansion.AnchorColumn;
                var colPerm = ctl.myColumnPermutation;
                if (displayColumn == VirtualTreeConstant.NullIndex)
                {
                    settings |= AccItemSettings.BlankRow;
                    displayColumn = 0;
                    myColumnWidth = expansion.Width;
                }
                else
                {
                    nativeColumn = (colPerm != null) ? colPerm.GetNativeColumn(displayColumn) : displayColumn;
                    myColumnWidth = expansion.RightColumn - displayColumn + 1;
                }
                myDisplayColumn = displayColumn;
                myNativeColumn = nativeColumn;
                mySettings = settings;
            }
        private void DrawIndentLines(
            Graphics graphics, Color backColor, Color foreColor, int absIndex, int nativeColumn, VirtualTreeItemInfo info,
            VirtualTreeDisplayData tdd, int remainingWidth, int adjustedItemHeight, ref int textLeft)
        {
            var level = info.Level;
            var expandable = HasButtons && info.Expandable;
            var expanded = expandable && info.Expanded;

            Brush brush = null;
            try
            {
                // Fill the background with the given backColor.
                EnsureBrush(ref brush, backColor);

                if (0 == (myStyleFlags & VTCStyleFlags.MaskHasIndentBitmaps))
                {
                    if (level > 0)
                    {
                        textLeft = level * myIndentWidth;
                        graphics.FillRectangle(brush, 0, 0, textLeft, adjustedItemHeight);
                    }
                }
                else
                {
                    int iRow;
                    var iColumn = 0;
                    if (!HasLines) // HasLines and HasRootLines are synchronized, only HasButtons (and possibly HasRootButtons) is set
                    {
                        if (HasRootButtons && (nativeColumn == 0 || !info.SimpleCell))
                        {
                            ++level;
                        }
                        if (level > 0)
                        {
                            textLeft = level * myIndentWidth;
                            if (info.Blank)
                            {
                                if (tdd.Image != -1)
                                {
                                    textLeft += myImageWidth;
                                }
                                if (tdd.StateImageIndex != -1)
                                {
                                    textLeft += myImageWidth;
                                }
                            }
                            // We're just looking at buttons
                            if (expandable)
                            {
                                --level;
                                iColumn = 0;
                                iRow = expanded ? 1 : 0;
                                var destRect = new Rectangle(textLeft - myIndentWidth, 0, myIndentWidth, adjustedItemHeight);
                                if (destRect.Left < remainingWidth)
                                {
                                    // Ensure indent image doesn't draw outside bounding rectangle for this column
                                    if (destRect.Right > remainingWidth)
                                    {
                                        destRect.Width = remainingWidth - destRect.X;
                                    }
                                    graphics.DrawImage(
                                        GetIndentBitmap(backColor, foreColor), destRect, 0, iRow * myItemHeight, destRect.Width,
                                        adjustedItemHeight, GraphicsUnit.Pixel);
                                }
                            }
                        }
                        if (level > 0)
                        {
                            graphics.FillRectangle(brush, 0, 0, level * myIndentWidth, adjustedItemHeight);
                        }
                    }
                    else
                    {
                        // Determine the row to blit based on expansion state
                        // The rows are laid out {no expansion, plus, minus}
                        // The columns are laid out {level bmp, middle, bottom, top, single}
                        iRow = expandable ? (expanded ? 2 : 1) : 0;

                        // Determine the column to blit based on the position in the list
                        //						if (relIndex == (branch.ItemCount - 1))
                        if (info.LastBranchItem)
                        {
                            // Last item
                            //							if (HasRootLines && (branch.ItemCount == 1))
                            //							if (info.Blank)
                            //							{
                            //								skipGlyph = true;
                            //								levelAdjust = 1;
                            //							}
                            //							else
                            if (info.FirstBranchItem)
                            {
                                iColumn = (level == 0) ? 4 : 2;
                            }
                            else
                            {
                                iColumn = 2;
                            }
                        }
                            //						else if (info.Blank)
                            //						{
                            //							levelAdjust = 1;
                            //							if (info.Expanded)
                            //							{
                            //								iColumn = 0;
                            //								iRow = 0;
                            //							}
                            //							else
                            //							{
                            //								skipGlyph = true;
                            //							}
                            //						}
                        else
                        {
                            //							if ((relIndex == 0) && HasRootLines)
                            if (info.FirstBranchItem
                                && HasRootLines
                                && (nativeColumn == 0 || !info.SimpleCell))
                            {
                                iColumn = (level == 0) ? 3 : 1;
                            }
                            else
                            {
                                iColumn = 1;
                            }
                        }

                        var iStartColumn = 0;
                        if ((absIndex & 1) == 1
                            && (myItemHeight & 1) == 1)
                        {
                            // in the odd item height case, use different bitmaps in alternating rows to keep the gridlines looking good.
                            // see comment in CreateIndentBmp() for more info.
                            iStartColumn = (HasRootLines || HasRootButtons) ? 5 : 3;
                        }
                        iColumn += iStartColumn;

                        // Blit in the level bitmaps. This is trickier than it looks because
                        // a check is required at each level to see if the parent root lines
                        // are required.
                        if (GetAnyStyleFlag(VTCStyleFlags.HasRootLines | VTCStyleFlags.HasRootButtons)
                            && (nativeColumn == 0 || !info.SimpleCell))
                        {
                            ++level;
                        }

                        if (level > 0)
                        {
                            var bmp = GetIndentBitmap(backColor, foreColor);
                            var cxSrc = myIndentWidth;
                            var cySrc = myItemHeight;
                            textLeft = level * cxSrc;
                            var skipGlyph = false;
                            var destRect = new Rectangle((level - 1) * cxSrc, 0, cxSrc, cySrc);

                            if (info.Blank)
                            {
                                if (tdd.Image != -1)
                                {
                                    textLeft += myImageWidth;
                                }
                                if (tdd.StateImageIndex != -1)
                                {
                                    textLeft += myImageWidth;
                                }
                                iColumn = iStartColumn;
                                iRow = 0;
                                if (info.LastBranchItem)
                                {
                                    skipGlyph = true;
                                }
                                if (info.Expanded)
                                {
                                    destRect.Offset(cxSrc, 0);
                                    if (destRect.Left < remainingWidth)
                                    {
                                        // Ensure indent image doesn't draw outside bounding rectangle for this column.
                                        if (destRect.Right <= remainingWidth)
                                        {
                                            graphics.DrawImage(bmp, destRect, iColumn * cxSrc, 0, cxSrc, cySrc, GraphicsUnit.Pixel);
                                        }
                                        else
                                        {
                                            graphics.DrawImage(
                                                bmp, new Rectangle(destRect.X, destRect.Y, remainingWidth - destRect.X, destRect.Height),
                                                iColumn * cxSrc, 0, remainingWidth - destRect.X, cySrc, GraphicsUnit.Pixel);
                                        }
                                    }
                                    destRect.Offset(-cxSrc, 0);
                                }
                            }

                            var xSrc = iColumn * cxSrc;
                            var ySrc = iRow * myItemHeight; //cySrc;

                            if (!skipGlyph
                                && destRect.Left < remainingWidth)
                            {
                                // Do the initial glyph.  Ensure indent image doesn't draw outside bounding rectangle for this column.
                                if (destRect.Right <= remainingWidth)
                                {
                                    graphics.DrawImage(bmp, destRect, xSrc, ySrc, cxSrc, cySrc, GraphicsUnit.Pixel);
                                }
                                else
                                {
                                    graphics.DrawImage(
                                        bmp, new Rectangle(destRect.X, destRect.Y, remainingWidth - destRect.X, destRect.Height), xSrc, ySrc,
                                        remainingWidth - destRect.X, cySrc, GraphicsUnit.Pixel);
                                }
                            }

                            if (level > 1)
                            {
                                // Move back to the parent glyph, reset cySrc and destRect to non-adjusted item height.
                                xSrc = iStartColumn * cxSrc;
                                cySrc = destRect.Height = myItemHeight;

                                //								int parentRelIndex;
                                //								int dummyLevel;
                                //								IBranch parentBranch;
                                var parentIndex = absIndex;
                                VirtualTreeItemInfo parentInfo;
                                while (--level > 0)
                                {
                                    destRect.Offset(-cxSrc, 0);
                                    parentIndex = myTree.GetParentIndex(parentIndex, nativeColumn);

                                    if (destRect.Left < remainingWidth)
                                    {
                                        parentInfo = myTree.GetItemInfo(parentIndex, nativeColumn, true);
                                        //									if ((parentRelIndex + 1) == parentBranch.ItemCount)
                                        if (parentInfo.LastBranchItem)
                                        {
                                            graphics.FillRectangle(brush, destRect.X, destRect.Y, cxSrc, adjustedItemHeight);
                                                // fill adjusted rectangle so we don't paint over gridlines.
                                        }
                                        else
                                        {
                                            // Ensure indent image doesn't draw outside bounding rectangle for this column.
                                            if (destRect.Right <= remainingWidth)
                                            {
                                                graphics.DrawImage(bmp, destRect, xSrc, ySrc, cxSrc, cySrc, GraphicsUnit.Pixel);
                                            }
                                            else
                                            {
                                                graphics.DrawImage(
                                                    bmp, new Rectangle(destRect.X, destRect.Y, remainingWidth - destRect.X, destRect.Height),
                                                    xSrc, ySrc, remainingWidth - destRect.X, cySrc, GraphicsUnit.Pixel);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            finally
            {
                CleanBrush(ref brush, backColor);
            }
        }
            public AccPrimaryItem(
                VirtualTreeControl ctl, int row, int displayColumn, int nativeColumn, AccItemSettings settings, ref VirtualTreeItemInfo info)
                :
                    base(ctl, row, displayColumn, nativeColumn, settings, ref info)
            {
                if (ctl.MultiColumnTree != null)
                {
                    var mcBranch = info.Branch as IMultiColumnBranch;
                    if (mcBranch != null)
                    {
                        // If Column is not 0, then we're looking at an expandable cell. Expandable
                        // cells cannot have multiple columns.
                        if (info.Column == 0)
                        {
                            var childColumnCount = (0 == (info.Branch.Features & BranchFeatures.JaggedColumns))
                                                       ? mcBranch.ColumnCount
                                                       : mcBranch.GetJaggedColumnCount(info.Row);

                            myNativeChildColumns = myDisplayedChildColumns = childColumnCount - 1;

                            var colPerm = ctl.myColumnPermutation;
                            if (colPerm != null)
                            {
                                // We have to ask on a per-column basis if the given column is
                                // currently displayed.
                                var columnBound = nativeColumn + childColumnCount;
                                childColumnCount = 0;
                                for (var i = nativeColumn + 1; i < columnBound; ++i)
                                {
                                    if (colPerm.GetPermutedColumn(i) != -1)
                                    {
                                        ++childColumnCount;
                                    }
                                }
                                myDisplayedChildColumns = childColumnCount;
                            }
                        }
                    }
                }
                if (ctl.Tree.IsExpanded(myRow, myNativeColumn))
                {
                    myChildItems = ctl.Tree.GetExpandedBranch(myRow, myNativeColumn).Branch.VisibleItemCount;
                }
            }
 public AccSimpleCell(
     VirtualTreeControl ctl, int row, int displayColumn, int nativeColumn, AccItemSettings settings, ref VirtualTreeItemInfo info)
     :
         base(ctl, row, displayColumn, nativeColumn, settings, ref info)
 {
     value = info.Branch.GetAccessibleValue(info.Row, info.Column);
 }
            /// <summary>
            ///     Construct the base class of an accessibility item for this object
            /// </summary>
            /// <param name="ctl">The parent control</param>
            /// <param name="row">The current row</param>
            /// <param name="displayColumn">The display column.</param>
            /// <param name="nativeColumn">The native column.</param>
            /// <param name="settings">Miscellaneous settings for the object</param>
            /// <param name="info">The info for this cell. Gives the info for column 0 for a blank row.</param>
            public AccItem(
                VirtualTreeControl ctl,
                int row,
                int displayColumn,
                int nativeColumn,
                AccItemSettings settings,
                ref VirtualTreeItemInfo info)
            {
                // Blank row is calculated explicitly, ignore it if it is passed in
                settings = (AccItemSettings)((int)settings & ~(int)(AccItemSettings.BlankRow));

                var tree = ctl.Tree;

                // Get information about the branch and tree state at this
                // position in the tree.
                Debug.Assert(!info.Blank); // Adjust row and column before creating here to take care of blanks
                if (displayColumn < 0)
                {
                    displayColumn = 0;
                }
                if (nativeColumn < 0)
                {
                    nativeColumn = 0;
                }

                if (ctl.MultiColumnTree != null)
                {
                    // Adjust the passed in row and column so that it is on a non-blank item,
                    // and find out how far the blank range extends from that anchor point.
                    // Note that even a single-column branch can have blank columns to the
                    // right (or left, with permutations), so we always need to do GetBlankExpansion.
                    var expansion = tree.GetBlankExpansion(row, displayColumn, ctl.myColumnPermutation);
                    row = expansion.TopRow;
                    myRowHeight = expansion.Height;
                    if (expansion.AnchorColumn != -1)
                    {
                        displayColumn = expansion.AnchorColumn;
                        myColumnWidth = expansion.RightColumn - displayColumn + 1; // Ignore blanks to the left, don't use Width
                    }
                    else
                    {
                        settings |= AccItemSettings.BlankRow;
                        myColumnWidth = expansion.Width;
                    }
                }
                else
                {
                    myRowHeight = myColumnWidth = 1;
                }

                // Cache the information we need
                myCtl = ctl;
                ctl.GetAccessibilityTextFields(
                    row, displayColumn, ref info, out myName, out myValue, out myDescription, out myHelpFile, out myHelpId, out myState,
                    out myCheckBoxContent);
                myRow = row;
                myDisplayColumn = displayColumn;
                myNativeColumn = nativeColumn;
                mySettings = settings;
                myLevel = info.Level;
                if (info.Expandable)
                {
                    if (info.Expanded)
                    {
                        myState |= AccessibleStates.Expanded;
                    }
                    else
                    {
                        myState |= AccessibleStates.Collapsed;
                    }
                }
                if (0 != (settings & AccItemSettings.HiddenItem))
                {
                    myState |= AccessibleStates.Invisible;
                }
                else if (Rectangle.Empty == myCtl.GetAccessibilityLocation(myRow, myDisplayColumn, myRowHeight, myColumnWidth))
                {
                    myState |= (AccessibleStates.Invisible | AccessibleStates.Offscreen);
                }
                ctl.SetAccessibilityState(row, displayColumn, settings, ref myState);
            }
 /// <summary>
 ///     Helper routine to figure out if a given column object is a simple cell or a complex item.
 /// </summary>
 public static bool IsSimpleItem(VirtualTreeControl ctl, int baseRow, int nativeBaseColumn, int localColumn)
 {
     if (localColumn == 0)
     {
         return false; // items in the first column are never simple
     }
     var simpleCell = true;
     var tree = ctl.Tree;
     var info = tree.GetItemInfo(baseRow, nativeBaseColumn, false);
     var mcBranch = info.Branch as IMultiColumnBranch;
     if (mcBranch != null)
     {
         var nativeColumn = nativeBaseColumn + localColumn;
         var style = mcBranch.ColumnStyles(localColumn);
         var colInfo = new VirtualTreeItemInfo();
         switch (style)
         {
             case SubItemCellStyles.Expandable:
                 // Use a simple cell unless the item is expandable. An item
                 // in an expandable column cannot have subitems, so
                 // we will not need a column object for this purpose.
                 simpleCell = !info.Branch.IsExpandable(info.Row, localColumn);
                 break;
             case SubItemCellStyles.Mixed:
             case SubItemCellStyles.Complex:
                 colInfo = tree.GetItemInfo(baseRow, nativeColumn, true);
                 if (colInfo.Column == 0)
                 {
                     var columns = (0 == (info.Branch.Features & BranchFeatures.JaggedColumns))
                                       ? mcBranch.ColumnCount
                                       : mcBranch.GetJaggedColumnCount(info.Row);
                     // The data is provided by a different branch. The item is simple only
                     // if the branch has one unexpandable item and no sub items.
                     if (!(colInfo.Branch.VisibleItemCount == 1 &&
                           !colInfo.Branch.IsExpandable(0, 0) &&
                           (localColumn < columns ||
                            (null != (colInfo.Branch as IMultiColumnBranch) &&
                             0 == tree.GetSubItemCount(baseRow, nativeColumn)))))
                     {
                         simpleCell = false;
                     }
                 }
                 else if (style == SubItemCellStyles.Mixed)
                 {
                     goto case SubItemCellStyles.Expandable;
                 }
                 break;
         }
     }
     return simpleCell;
 }
 /// <summary>
 ///     Return either a Cell or Column object, depending on the branch settings
 /// </summary>
 /// <param name="ctl">The parent control</param>
 /// <param name="baseRow">The row coordinate</param>
 /// <param name="nativeBaseColumn">The column coordinate for the owning branch</param>
 /// <param name="localColumn">The native column offset</param>
 /// <param name="returnColumn">Return an AccColumn object if this is true, otherwise return the AccPrimaryItem directly</param>
 /// <returns>An AccSimpleCell or AccColumn</returns>
 public static AccessibleObject GetColumnObject(
     VirtualTreeControl ctl, int baseRow, int nativeBaseColumn, int localColumn, bool returnColumn)
 {
     // Note:  if this logic changes, corresponding change should be made to IsSimpleItem below.
     Debug.Assert(localColumn > 0);
     AccessibleObject retVal = null;
     var tree = ctl.Tree;
     var info = tree.GetItemInfo(baseRow, nativeBaseColumn, false);
     var mcBranch = info.Branch as IMultiColumnBranch;
     if (mcBranch != null)
     {
         var simpleCell = true;
         var useColInfo = false;
         var nativeColumn = nativeBaseColumn + localColumn;
         var displayColumn = nativeColumn;
         var colPerm = ctl.myColumnPermutation;
         var settings = AccItemSettings.None;
         if (colPerm != null)
         {
             displayColumn = colPerm.GetPermutedColumn(nativeColumn);
             if (displayColumn == -1)
             {
                 displayColumn = 0;
                 settings |= AccItemSettings.HiddenItem;
             }
         }
         var style = mcBranch.ColumnStyles(localColumn);
         var colInfo = new VirtualTreeItemInfo();
         style = mcBranch.ColumnStyles(localColumn);
         switch (style)
         {
             case SubItemCellStyles.Expandable:
                 // Use a simple cell unless the item is expandable. An item
                 // in an expandable column cannot have subitems, so
                 // we will not need a column object for this purpose.
                 simpleCell = !info.Branch.IsExpandable(info.Row, localColumn);
                 break;
             case SubItemCellStyles.Mixed:
             case SubItemCellStyles.Complex:
                 colInfo = tree.GetItemInfo(baseRow, nativeColumn, true);
                 if (colInfo.Column == 0)
                 {
                     var columns = (0 == (info.Branch.Features & BranchFeatures.JaggedColumns))
                                       ? mcBranch.ColumnCount
                                       : mcBranch.GetJaggedColumnCount(info.Row);
                     // The data is provided by a different branch. The item is simple only
                     // if the branch has one unexpandable item and no sub items.
                     if (!(colInfo.Branch.VisibleItemCount == 1 &&
                           !colInfo.Branch.IsExpandable(0, 0) &&
                           (localColumn < columns ||
                            (null != (colInfo.Branch as IMultiColumnBranch) &&
                             0 == tree.GetSubItemCount(baseRow, nativeColumn)))))
                     {
                         simpleCell = false;
                     }
                     useColInfo = true;
                 }
                 else if (style == SubItemCellStyles.Mixed)
                 {
                     goto case SubItemCellStyles.Expandable;
                 }
                 break;
         }
         if (simpleCell)
         {
             if (useColInfo)
             {
                 retVal = new AccSimpleCell(ctl, baseRow, displayColumn, nativeColumn, settings, ref colInfo);
             }
             else
             {
                 var cellInfo = tree.GetItemInfo(baseRow, nativeColumn, true);
                 if (!cellInfo.Blank)
                 {
                     retVal = new AccSimpleCell(ctl, baseRow, displayColumn, nativeColumn, settings, ref cellInfo);
                 }
             }
         }
         else if (returnColumn)
         {
             if (useColInfo)
             {
                 retVal = new AccColumn(ctl, baseRow, displayColumn, nativeColumn, settings, ref colInfo);
             }
             else
             {
                 var cellInfo = tree.GetItemInfo(baseRow, nativeBaseColumn + localColumn, true);
                 retVal = new AccColumn(ctl, baseRow, displayColumn, nativeColumn, settings, ref cellInfo);
             }
         }
         else
         {
             if (useColInfo)
             {
                 retVal = new AccPrimaryItem(ctl, baseRow, displayColumn, nativeColumn, settings, ref colInfo);
             }
             else
             {
                 var cellInfo = tree.GetItemInfo(baseRow, nativeBaseColumn + localColumn, true);
                 retVal = new AccPrimaryItem(ctl, baseRow, displayColumn, nativeColumn, settings, ref cellInfo);
             }
         }
     }
     return retVal;
 }
Example #15
0
        private VirtualTreeItemInfo GetItemInfo(ref ITEMPOSITION pos, int column, bool setFlags, bool ignoreMultiColumn, bool lastSubItem)
        {
            var info = new VirtualTreeItemInfo(pos.ParentNode.Branch, pos.Index, column, pos.Level);
            var blankItem = ignoreMultiColumn ? false : pos.IsBlank(column);
            info.Blank = blankItem;

            if (setFlags)
            {
                if (!ignoreMultiColumn && MultiColumnSupport)
                {
                    TREENODE tnChild;
                    if (blankItem)
                    {
                        if (column >= pos.ParentNode.GetColumnCount(pos.Index))
                        {
                            // If the item is after all supported columns then
                            // just let it draw blank by leaving all flags clear.
                            info.ClearLevel();
                        }
                        else
                        {
                            Debug.Assert(pos.SubItemOffset > 0);
                            tnChild = pos.ParentNode.GetChildNode(pos.Index);
                            Debug.Assert(tnChild != null); // Can't get a subitem offset without a node
                            if (column == 0)
                            {
                                // A blank item in the first column
                                info.TrailingItem = pos.SubItemOffset == tnChild.ImmedSubItemGain;
                                info.LastBranchItem = (pos.Index + 1) == pos.ParentNode.ImmedCount;
                                info.FirstBranchItem = pos.Index == 0;
                                info.Expanded = tnChild.Expanded && (tnChild.ImmedCount > 0);
                                    // Required information to draw lines down to expanded item
                            }
                            else
                            {
                                // A blank item in subitem column
                                info.ClearLevel();
                                info.TrailingItem = pos.SubItemOffset == tnChild.ImmedSubItemGain;
                            }
                        }
                    } // if (blankItem)
                    else if (!pos.ParentNode.MultiColumn)
                    {
                        info.Expanded = pos.IsExpanded(column);
                        info.Expandable = info.Expanded || pos.IsExpandable(column);
                        info.FirstBranchItem = pos.Index == 0;
                        info.LastBranchItem = pos.ParentNode.Branch.VisibleItemCount == (pos.Index + 1);
                        if (pos.ParentNode.InSubItemColumn)
                        {
                            info.LeadingItem = info.FirstBranchItem && pos.ParentNode.ComplexSubItem;
                            info.TrailingItem = lastSubItem;
                            info.SimpleCell = info.Level == 0 && pos.ParentNode.NoChildExpansion;
                        }
                        else
                        {
                            info.TrailingItem = info.LeadingItem = true;
                        }
                    }
                    else if (column == 0)
                    {
                        info.LeadingItem = true;
                        info.FirstBranchItem = pos.Index == 0;
                        info.LastBranchItem = (pos.Index + 1) == pos.ParentNode.ImmedCount;
                        tnChild = pos.ParentNode.GetChildNode(pos.Index);
                        if (tnChild == null)
                        {
                            info.TrailingItem = true;
                            info.Expandable = pos.IsExpandable(0); //column == 0
                        }
                        else
                        {
                            info.TrailingItem = tnChild.ImmedSubItemGain == 0;
                            info.Expanded = pos.IsExpanded(0); // column == 0
                            info.Expandable = info.Expanded || pos.IsExpandable(0);
                        }
                        info.SimpleCell = info.Level == 0 && pos.ParentNode.NoChildExpansion;
                    } // else if (column == 0)
                    else
                    {
                        info.LeadingItem = info.FirstBranchItem = true;
                        info.LastBranchItem = true;
                        tnChild = pos.ParentNode.GetChildNode(pos.Index);
                        if (tnChild != null)
                        {
                            info.TrailingItem = tnChild.ImmedSubItemGain == 0;
                        }
                        else
                        {
                            info.TrailingItem = true;
                        }
                        info.Expanded = pos.IsExpanded(column);
                        info.Expandable = info.Expanded || pos.IsExpandable(column);
                        info.SimpleCell = info.Level == 0 && !info.Expandable;
                    } // else
                } // if (MultiColumnSupport)
                else
                {
                    Debug.Assert(column == 0);
                    if (!blankItem)
                    {
                        info.Expanded = pos.IsExpanded(column);
                        info.Expandable = info.Expanded ? true : pos.IsExpandable(column);
                    }
                    info.FirstBranchItem = pos.Index == 0;
                    info.LastBranchItem = pos.ParentNode.Branch.VisibleItemCount == (pos.Index + 1);
                    info.LeadingItem = info.TrailingItem = true;
                } // else
            }
            return info;
        }
 // SCROLLING_FINISHED
 private int ListItemStringWidth(Graphics graphics, ref VirtualTreeItemInfo info, out int imageWidth)
 {
     return ListItemStringWidth(graphics, ref info, null, out imageWidth);
 }
 /// <summary>
 ///     Compare two VirtualTreeItemInfo structures
 /// </summary>
 /// <param name="operand1">Left operand</param>
 /// <param name="operand2">Right operand</param>
 /// <returns>true if operands are equal</returns>
 public static bool Compare(VirtualTreeItemInfo operand1, VirtualTreeItemInfo operand2)
 {
     return(operand1.myBranch == operand2.myBranch && operand1.myColumn == operand2.myColumn && operand1.myRow == operand2.myRow &&
            operand1.myLevel == operand2.myLevel && operand1.myFlags == operand2.myFlags);
 }
        private void GetAccessibilityTextFields(
            int row, int column, ref VirtualTreeItemInfo info, out string name, out string value, out string description,
            out string helpFile, out int helpId, out AccessibleStates state, out bool contentIsCheckBox)
        {
            var accData = info.Branch.GetAccessibilityData(info.Row, info.Column);
            helpFile = accData.HelpFile;
            if (helpFile == null)
            {
                helpFile = string.Empty;
            }
            helpId = accData.HelpContextId;
            AccessibilityReplacementField[] replacementFields;
            var locValue = info.Branch.GetAccessibleValue(info.Row, info.Column);
            var locName = accData.NameFormatString;
            if (locName == null
                || locName.Length == 0)
            {
                locName = info.Branch.GetAccessibleName(info.Row, info.Column);
                if (locName == null)
                {
                    locName = string.Empty;
                }
            }
            else
            {
                replacementFields = accData.NameReplacementFields as AccessibilityReplacementField[];
                if (replacementFields != null)
                {
                    locName = FormatReplacementFields(
                        row, column, ref info, locName, replacementFields, accData.ImageDescriptions as string[],
                        accData.StateImageDescriptions as string[]);
                }
            }
            var locDesc = accData.DescriptionFormatString;
            if (locDesc == null
                || locDesc.Length == 0)
            {
                locDesc = info.Branch.GetTipText(info.Row, info.Column, ToolTipType.Icon);
                if (locDesc == null
                    || locDesc.Length == 0)
                {
                    locDesc = locName;
                }
            }
            else
            {
                replacementFields = accData.DescriptionReplacementFields as AccessibilityReplacementField[];
                if (replacementFields != null)
                {
                    locDesc = FormatReplacementFields(
                        row, column, ref info, locDesc, replacementFields, accData.ImageDescriptions as string[],
                        accData.StateImageDescriptions as string[]);
                }
            }
            var locState = AccessibleStates.None;
            var displayData = info.Branch.GetDisplayData(
                info.Row, info.Column,
                new VirtualTreeDisplayDataMasks(
                    VirtualTreeDisplayMasks.Image | VirtualTreeDisplayMasks.ImageOverlays | VirtualTreeDisplayMasks.StateImage, 0));
            contentIsCheckBox = false;
            if (displayData.StateImageIndex >= 0)
            {
                var states = (displayData.StateImageList == null)
                                 ? myStateImageAccessibleStates
                                 : accData.StateImageAccessibleStates as AccessibleStates[];
                // Fixes 342626	- With Windows Eye installed, first component created throws benign "Object reference not set to an object"	
                // Added check that states is null.
                // v-matbir - 8/13/04
                if (states != null
                    && displayData.StateImageIndex < states.Length)
                {
                    locState = states[displayData.StateImageIndex];
                }

                // treat the content as a check box if the StandardCheckBoxes property is true, the state
                // image index is in the appropriate range, and there is no custom state imagelist.
                contentIsCheckBox = StandardCheckBoxes
                                    && displayData.StateImageIndex <= LastStandardCheckBoxImageIndex
                                    && displayData.StateImageList == null;
            }
            name = locName;
            value = locValue;
            description = locDesc;
            state = locState;
        }