/// <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; } }
/// <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; }