// 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;
            }
 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);
 }
            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;
                }
            }
            /// <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);
            }
        private void DoAccessibilitySelectionChange(int row, int column, AccItemSettings settings, AccessibleSelection selectionState)
        {
            if (0 != (selectionState & AccessibleSelection.TakeSelection))
            {
                // TakeSelection may not be combined with any of these
                if (0 != (selectionState
                          & (AccessibleSelection.ExtendSelection | AccessibleSelection.AddSelection | AccessibleSelection.RemoveSelection)))
                {
                    throw new COMException(String.Empty, NativeMethods.E_INVALIDARG);
                }

                // set column appropriately
                if (mySelectionColumn != column
                    && (0 == (settings & (AccItemSettings.BlankRow | AccItemSettings.HiddenItem))))
                {
                    SetSelectionColumn(column, false);
                }

                if (GetStyleFlag(VTCStyleFlags.MultiSelect))
                {
                    ClearSelection(true);
                    SetSelected(row, true);
                    DoSelectionChanged();
                    FireWinEventsForSelection(false, false, ModifySelectionAction.None);
                    if (0 != (selectionState & AccessibleSelection.TakeFocus))
                    {
                        CaretIndex = AnchorIndex = row;
                    }
                }
                else
                {
                    // CurrentIndex setter sets selection and fires events in single select mode.
                    CurrentIndex = row;
                }
            }
            else if (0 != (selectionState & AccessibleSelection.ExtendSelection))
            {
                // ExtendSelection only valid for extended multi-select, and requires valid anchor.
                if (!GetStyleFlag(VTCStyleFlags.ExtendedMultiSelect)
                    || AnchorIndex < 0)
                {
                    throw new COMException(String.Empty, NativeMethods.E_INVALIDARG);
                }

                // set column appropriately
                if (mySelectionColumn != column
                    && (0 == (settings & (AccItemSettings.BlankRow | AccItemSettings.HiddenItem))))
                {
                    SetSelectionColumn(column, false);
                }

                // May use ExtendSelection to select or deselect a range.  If AddSelection/RemoveSelection are specified, use to determine whether we should select or deselect,
                // otherwise use current selected state of anchor index.
                bool select;
                if (0 != (selectionState & (AccessibleSelection.AddSelection | AccessibleSelection.RemoveSelection)))
                {
                    select = 0 != (selectionState & AccessibleSelection.AddSelection);
                }
                else
                {
                    select = IsSelected(AnchorIndex);
                }
                SetCurrentExtendedMultiSelectIndex(
                    row, true, false, select ? ModifySelectionAction.Select : ModifySelectionAction.Clear, select);
            }
            else if (0 != (selectionState & (AccessibleSelection.AddSelection | AccessibleSelection.RemoveSelection)))
            {
                // AddSelection/RemoveSelection only valid for multi-select, and may not be combined with any of these
                if (!GetStyleFlag(VTCStyleFlags.MultiSelect)
                    || (selectionState
                        != (selectionState
                            & (AccessibleSelection.AddSelection | AccessibleSelection.RemoveSelection | AccessibleSelection.TakeSelection))))
                {
                    throw new COMException(String.Empty, NativeMethods.E_INVALIDARG);
                }

                // set column appropriately
                if (mySelectionColumn != column
                    && (0 == (settings & (AccItemSettings.BlankRow | AccItemSettings.HiddenItem))))
                {
                    SetSelectionColumn(column, false);
                }

                var add = (0 != (selectionState & AccessibleSelection.AddSelection));
                SetSelected(row, add);
                DoSelectionChanged();
                FireWinEventsForSelection(false, true, add ? ModifySelectionAction.Select : ModifySelectionAction.Clear);

                if (0 != (selectionState & AccessibleSelection.TakeFocus))
                {
                    CaretIndex = AnchorIndex = row;
                }
            }
            else if (0 != (selectionState & AccessibleSelection.TakeFocus))
            {
                if (GetStyleFlag(VTCStyleFlags.MultiSelect))
                {
                    CaretIndex = AnchorIndex = row;
                    DoSelectionChanged();
                }
                else
                {
                    CurrentIndex = row; // TakeFocus behaves the same as TakeSelection in single-select mode.
                }
            }
            else
            {
                throw new COMException(String.Empty, NativeMethods.E_FAIL);
            }
        }
 private void SetAccessibilityState(int row, int column, AccItemSettings settings, ref AccessibleStates state)
 {
     if (0 == (settings & AccItemSettings.BlankRow))
     {
         state |= AccessibleStates.Selectable | AccessibleStates.Focusable;
         // UNDONE: Also need to call ResolveSelectionColumn for multiselect trees
         // UNDONE: Is there any way to check IsDrawWithFocusWindow here?
         if (mySelectionColumn == column
             && row == CurrentIndex
             && Focused)
         {
             state |= AccessibleStates.Focused;
         }
         // Report selection state if row is selected, and this is the current column
         // or MultiColumnHighlight is set, in which case selection will be drawn across the entire row.
         if ((mySelectionColumn == column || MultiColumnHighlight)
             && IsSelected(row))
         {
             state |= AccessibleStates.Selected;
         }
     }
 }