/// <summary>
 ///     Compare two VirtualTreeCoordinate 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(VirtualTreeCoordinate operand1, VirtualTreeCoordinate operand2)
 {
     return operand1.myColumn == operand2.myColumn && operand1.myRow == operand2.myRow;
 }
        /// <summary>
        ///     The displayed data for the branch has changed, and
        ///     any views on this tree need to be notified.
        /// </summary>
        /// <param name="changeData">The DisplayDataChangedData structure</param>
        protected void DisplayDataChanged(DisplayDataChangedData changeData)
        {
            var branch = changeData.Branch;
            var column = changeData.Column;
            var changes = changeData.Changes;
            if (column >= ColumnCount)
            {
                return;
            }
            var fireNormalEvent = OnDisplayDataChanged != null;
            var fireSingleColumnEvent = column == 0 && GetStateFlag(TreeStateFlags.FireSingleColumnOnDisplayDataChanged);
            if (!(fireNormalEvent || fireSingleColumnEvent))
            {
                return;
            }
            ITree singleTree = null;
            SingleColumnView singleView = null;
            if (fireSingleColumnEvent)
            {
                singleTree = SingleColumnTree;
                singleView = singleTree as SingleColumnView;
            }
            var tn = LocateTrackedNode(branch);
            Debug.Assert(tn != null); //Expect LocateTrackedNode to throw otherwise
            var coordinate = new VirtualTreeCoordinate();
            int prevAbsIndex;
            int prevAbsIndexSingleColumn;
            int reportCount;
            int reportCountSingleColumn;
            int count;
            int startRow;
            int singleColumnSubItemAdjust;
            //UNDONE: Does firing the event after we get the next node adversely affect the
            //performance of the node tracking algorithm.
            while (tn != null)
            {
                prevAbsIndex = prevAbsIndexSingleColumn = -2; // Set to -2 so that first diff check is never 1
                reportCount = reportCountSingleColumn = 0;
                if (changeData.StartRow == -1)
                {
                    startRow = 0;
                    count = tn.ImmedCount;
                }
                else
                {
                    startRow = changeData.StartRow;
                    count = changeData.Count;
                }
                while (count > 0)
                {
                    coordinate = FindAbsoluteIndex(tn, startRow, out singleColumnSubItemAdjust);
                    if (coordinate.IsValid)
                    {
                        if (fireNormalEvent)
                        {
                            if (((coordinate.Row - prevAbsIndex) == 1)
                                || (reportCount == 0))
                            {
                                ++reportCount; //Wait to fire the event until we find something discontiguous
                            }
                            else
                            {
                                OnDisplayDataChanged(
                                    this,
                                    new DisplayDataChangedEventArgs(
                                        this, changes, prevAbsIndex - reportCount + 1, coordinate.Column + column, reportCount));
                                reportCount = 1;
                            }
                            prevAbsIndex = coordinate.Row;
                        }

                        if (fireSingleColumnEvent && coordinate.Column == 0)
                        {
                            if (((coordinate.Row - singleColumnSubItemAdjust - prevAbsIndexSingleColumn) == 1)
                                || (reportCountSingleColumn == 0))
                            {
                                ++reportCountSingleColumn; //Wait to fire the event until we find something discontiguous
                            }
                            else
                            {
                                singleView.myOnDisplayDataChanged(
                                    singleTree,
                                    new DisplayDataChangedEventArgs(
                                        singleTree, changes, prevAbsIndexSingleColumn - reportCountSingleColumn + 1, 0,
                                        reportCountSingleColumn));
                                reportCountSingleColumn = 1;
                            }
                            prevAbsIndexSingleColumn = coordinate.Row - singleColumnSubItemAdjust;
                        }

                        ++startRow;
                        --count;
                    }
                    else
                    {
                        break;
                    }
                }
                if (reportCount != 0)
                {
                    OnDisplayDataChanged(
                        this,
                        new DisplayDataChangedEventArgs(
                            this, changes, prevAbsIndex - reportCount + 1, coordinate.Column + column, reportCount));
                }
                if (reportCountSingleColumn != 0)
                {
                    singleView.myOnDisplayDataChanged(
                        singleTree,
                        new DisplayDataChangedEventArgs(
                            singleTree, changes, prevAbsIndexSingleColumn - reportCountSingleColumn + 1, 0, reportCountSingleColumn));
                }
                tn = tn.NextNode;
            }
        }
Exemple #3
0
 /// <summary>
 ///     Compare two VirtualTreeCoordinate 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(VirtualTreeCoordinate operand1, VirtualTreeCoordinate operand2)
 {
     return(operand1.myColumn == operand2.myColumn && operand1.myRow == operand2.myRow);
 }
        private bool ProcessKey(ProcessKeyResult result, ITreeGridDesignerBranch branch, int absIndex, int relIndex, int column)
        {
            var actionOccurred = false;
            var foundEditableColumn = false;
            var inLabelEdit = InLabelEdit;

            if (result.Action == KeyAction.Discard)
            {
                return true;
            }

            if (result.Action == KeyAction.Handle)
            {
                var treeDirection = TranslateNavigationDirection(result.Direction);
                if (result.StartLabelEdit)
                {
                    // key should just put us in edit mode
                    InLabelEdit = true;
                    // Alt + Down case - open drop down
                    if (result.Direction == NavigationDirection.Down)
                    {
                        var dropDown = LabelEditControl as TypeEditorHost;
                        if (dropDown != null)
                        {
                            dropDown.OpenDropDown();
                        }
                    }
                    return true; // currently, we don't allow combining this with other options
                }

                if (result.Delete)
                {
                    branch.Delete(relIndex, column);
                    // don't restore edit mode if we deleted something
                    inLabelEdit = false;
                }

                BatchDrawItem = true;
                if (inLabelEdit)
                {
                    var tridDesignerBranch = branch as TreeGridDesignerBranch;

                    if (tridDesignerBranch != null
                        && relIndex >= tridDesignerBranch.ElementCount)
                    {
                        // creator node edit.  unless the user has actually typed some text here,
                        // we treat this as non-edit mode (i.e, don't restore edit mode after navigation)
                        inLabelEdit = LabelEditControl.Text.Length > 0;
                    }
                }

                try
                {
                    InLabelEdit = false;

                    // the branch may block deactivation of the edit control,
                    // because of an incorrect entry, for example.  In that case,
                    // we should just get out.
                    if (InLabelEdit)
                    {
                        return false;
                    }

                    // expand branch first, if necesary
                    if (result.ExpandBranch)
                    {
                        // using column = 0 because TreeGrid designer
                        // doesn't support sub-item expansions.
                        if (!Tree.IsExpanded(absIndex, 0))
                        {
                            // the branch is requesting an expansion, but we can't do it.
                            // just get out and leave things the way they are.
                            if (!Tree.IsExpandable(absIndex, 0))
                            {
                                return false;
                            }

                            Tree.ToggleExpansion(absIndex, 0);
                            actionOccurred = true;
                        }
                    }

                    var branchType = branch.GetType();

                    if (result.ColumnType != null)
                    {
                        // limit search to a particular column
                        var newColumn = FindCurrentColumnOfType(result);

                        Debug.Assert(newColumn != -1, "Couldn't find column of type: " + result.ColumnType);
                        if ((treeDirection == TreeNavigation.RightColumn && column < newColumn)
                            || (treeDirection == TreeNavigation.LeftColumn && column > newColumn))
                        {
                            // in this case, we're done as long as the branch is of the appropriate type and supports navigation or is expandable, because we have
                            // the correct row/column indices.
                            column = newColumn;
                            foundEditableColumn = (result.BranchType == null || branchType == result.BranchType
                                                   || branchType.IsSubclassOf(result.BranchType)) &&
                                                  ((branch.GetValueSupported(relIndex, column)
                                                    & TreeGridDesignerValueSupportedStates.SupportsKeyboardNavigation) != 0
                                                   || (branch as IBranch).IsExpandable(relIndex, column));
                        }

                        if (!foundEditableColumn)
                        {
                            // need to do additional search, translate to an up or down search in this particular column
                            column = newColumn;
                            treeDirection = treeDirection == TreeNavigation.RightColumn ? TreeNavigation.Down : TreeNavigation.Up;
                        }
                    }

                    if (result.Delete)
                    {
                        // we are already focused on an editable column
                        InvalidateItem(CurrentIndex);
                        actionOccurred = true;
                    }
                    else
                    {
                        // search for next matching row/column
                        int oldAbsIndex;
                        while (!foundEditableColumn)
                        {
                            oldAbsIndex = absIndex;
                            if (treeDirection == TreeNavigation.LeftColumn
                                && column == 0)
                            {
                                absIndex--;
                                if (absIndex >= 0)
                                {
                                    var info = Tree.GetItemInfo(absIndex, 0, false);
                                    column = GetLastColumnIndex(info.Branch, info.Row);
                                }
                            }
                            else if (treeDirection == TreeNavigation.RightColumn
                                     && column == GetLastColumnIndex((IBranch)branch, relIndex))
                            {
                                absIndex++;
                                column = 0;
                            }
                            else if (result.ColumnType == null)
                            {
                                // search is not restricted to a particular column, so we translate up/down to 
                                // left/right search to give a better experience.
                                if (treeDirection == TreeNavigation.Up)
                                {
                                    absIndex--;
                                    treeDirection = TreeNavigation.LeftColumn;

                                    if (absIndex >= 0)
                                    {
                                        // handle jagged column cases
                                        var info = Tree.GetItemInfo(absIndex, 0, false);
                                        if (info.Branch != null)
                                        {
                                            column = GetLastColumnIndex(info.Branch, info.Row);
                                        }
                                    }
                                }
                                else if (treeDirection == TreeNavigation.Down)
                                {
                                    absIndex++;
                                    treeDirection = TreeNavigation.RightColumn;
                                    column = 0;
                                }
                            }

                            if (absIndex < 0
                                || absIndex >= Tree.VisibleItemCount)
                            {
                                break;
                            }

                            var coordinate = new VirtualTreeCoordinate(absIndex, column);
                            if (absIndex == oldAbsIndex)
                            {
                                // if the above didn't result in any navigation, ask the tree to do it itself.
                                coordinate = Tree.GetNavigationTarget(treeDirection, absIndex, column, ColumnPermutation);
                            }

                            if (coordinate.IsValid)
                            {
                                absIndex = coordinate.Row;
                                column = coordinate.Column;

                                if (oldAbsIndex != absIndex)
                                {
                                    // we've transitioned to a new row, retrieve new row data from the tree.
                                    var info = Tree.GetItemInfo(absIndex, 0, false);

                                    if (result.Local
                                        && branch != null
                                        && branch != info.Branch)
                                    {
                                        // stop search if we shouldn't go past current branch
                                        break;
                                    }

                                    branch = info.Branch as ITreeGridDesignerBranch;
                                    branchType = branch.GetType();
                                    relIndex = info.Row;
                                }

                                // allow focus on expandable cells or cells that support navigation that are of the appropriate branch type.  
                                if (branch != null
                                    &&
                                    (result.BranchType == null || branchType == result.BranchType
                                     || branchType.IsSubclassOf(result.BranchType))
                                    &&
                                    ((branch.GetValueSupported(relIndex, column)
                                      & TreeGridDesignerValueSupportedStates.SupportsKeyboardNavigation) != 0
                                     || (branch as IBranch).IsExpandable(relIndex, column)))
                                {
                                    foundEditableColumn = true;
                                    break;
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                    }

                    if (foundEditableColumn)
                    {
                        var currentIndex = CurrentIndex;

                        if (absIndex != currentIndex)
                        {
                            if (currentIndex != -1)
                            {
                                // currentIndex may be -1 if we toggled expansion,
                                // but in that case the base control will take care
                                // of the redraw
                                // TODO : is this a bug in the control?  shouldn't selection
                                // be restored after toggling expansion?
                                InvalidateItem(currentIndex);
                            }

                            CurrentIndex = absIndex;
                            actionOccurred = true;
                        }

                        if (column != CurrentColumn)
                        {
                            CurrentColumn = column;
                            actionOccurred = true;
                        }
                    }

                    InLabelEdit = inLabelEdit;
                }
                finally
                {
                    BatchDrawItem = false;
                }
            }
            return actionOccurred;
        }