private VirtualTreeLabelEditData(bool isValid, bool deferActivation) { myIsValid = isValid; myDeferActivation = deferActivation; myAlternateText = null; myCustomInPlaceEdit = null; myCustomCallback = null; myMaxTextLength = 0; }
/// <summary> /// Create new data for beginning a label edit. /// </summary> /// <param name="customInPlaceEdit">An alternate control instance or type for editing. Specify null for a standard edit control.</param> /// <param name="customCommit">An function to call on label commit. Specify null to use IBranch.CommitLabelEdit</param> /// <param name="alternateText">An alternate text. Specify null to use IBranch.GetText</param> /// <param name="maxTextLength">A maximum text length, or 0 for unbounded.</param> public VirtualTreeLabelEditData( object customInPlaceEdit, CommitLabelEditCallback customCommit, string alternateText, int maxTextLength) { myIsValid = true; myDeferActivation = false; myCustomInPlaceEdit = customInPlaceEdit; myCustomCallback = customCommit; myAlternateText = alternateText; myMaxTextLength = maxTextLength; }
/// <summary> /// Create new data for beginning a label edit. /// </summary> /// <param name="customInPlaceEdit">An alternate control instance or type for editing. Specify null for a standard edit control.</param> /// <param name="customCommit">An function to call on label commit. Specify null to use IBranch.CommitLabelEdit</param> public VirtualTreeLabelEditData(object customInPlaceEdit, CommitLabelEditCallback customCommit) : this(customInPlaceEdit, customCommit, null, 0) { }
private bool DismissLabelEdit(bool fCancel, bool fForceFocus) { if (GetStateFlag(VTCStateFlags.NoDismissEdit)) { return false; } var fOkToContinue = true; var edit = myInPlaceControl; if (edit == null) { // Also make sure there are no pending edits... CancelEditTimer(); return true; } var editCtl = edit.InPlaceControl; // Assume that if we are not visible that the window is in the // process of being destroyed and we should not process the // editing of the window... if (!NativeMethods.IsWindowVisible(Handle)) { fCancel = true; } // // We are using the Window Id of the control as a BOOL to // state if it is dirty or not. Debug.Assert(GetStateFlag(VTCStateFlags.LabelEditActive)); if (GetStateFlag(VTCStateFlags.LabelEditProcessing)) { // We are in the process of processing an update now, bail out return true; } else if (GetStateFlag(VTCStateFlags.LabelEditDirty)) { // The edit control is dirty so continue. SetStateFlag(VTCStateFlags.LabelEditProcessing, true); } else { // The edit control is not dirty so act like cancel. fCancel = true; SetStateFlag(VTCStateFlags.LabelEditProcessing, true); } var fCloseWindow = fCancel; var selectionColumn = -1; var iEdit = myEditIndex; // If we're canceling outright, then there is no reason to // notify the branch that the edit is being canceled. try { if (!fCancel) { // Deleting items can set myEditIndex to NullIndex if the program // deleted the items out from underneath us (while we are waiting // for the edit timer). if (iEdit != VirtualTreeConstant.NullIndex) { // Relocate the branch and item for the object and // ask them to commit. int nativeSelectionColumn; ResolveSelectionColumn(iEdit, out selectionColumn, out nativeSelectionColumn); var info = myTree.GetItemInfo(iEdit, nativeSelectionColumn, false); var editCode = (myCustomInPlaceCommit == null) ? info.Branch.CommitLabelEdit(info.Row, info.Column, editCtl.Text) : myCustomInPlaceCommit(info, editCtl); switch (editCode) { case LabelEditResult.AcceptEdit: //NYI: Need to adjust horizontal extent fCloseWindow = true; break; case LabelEditResult.CancelEdit: fCloseWindow = true; break; case LabelEditResult.BlockDeactivate: goto case LabelEditResult.CancelEdit; //NYI: Need to get a posting mechanism here, probably through //BeginInvoke, to call back and reopen the edit window at a later time. //Debug.Assert(!fCloseWindow); //SetStateFlag(VTCStateFlags.LabelEditProcessing, false); //myInPlaceControl.SelectAllText(); //break; default: Debug.Assert(false, "Invalid Enum Value"); // Nothing much to do except toss it fCloseWindow = true; break; } } else { fCloseWindow = true; } } } catch (Exception ex) { if (CriticalException.IsCriticalException(ex)) { fCloseWindow = false; // prevents us from doing work in finally block below in the case of a critical exception. throw; } fCloseWindow = true; fOkToContinue = false; if (!DisplayException(ex)) { throw; } } /* catch { fCloseWindow = true; fOkToContinue = false; throw; }*/ finally { if (fCloseWindow) { // Make sure the text redraws properly if (iEdit != VirtualTreeConstant.NullIndex && iEdit < ItemCount) { if (selectionColumn != -1) { int nativeSelectionColumn; ResolveSelectionColumn(iEdit, out selectionColumn, out nativeSelectionColumn); } InvalidateAreaForLabelEdit(iEdit, selectionColumn, editCtl); } SetStateFlag(VTCStateFlags.NoDismissEdit, true); // this is so that we don't recurse due to killfocus if (fForceFocus && !Focused) { Focus(); } editCtl.Hide(); SetStateFlag(VTCStateFlags.NoDismissEdit, false); // If we did not reenter edit mode before now reset the edit state // variables to NULL var disposeControl = (myInPlaceControl.Flags & VirtualTreeInPlaceControls.DisposeControl) != 0; if (myInPlaceControl == edit) { myInPlaceControl = null; myCustomInPlaceCommit = null; SetStateFlag(VTCStateFlags.LabelEditMask, false); myEditIndex = VirtualTreeConstant.NullIndex; } // done with the edit control -- if desired, we will // dispose of it. Otherwise, it's up to the branch if (disposeControl) { // Reset this flag, Dispose can have side effects SetStateFlag(VTCStateFlags.NoDismissEdit, true); editCtl.Dispose(); SetStateFlag(VTCStateFlags.NoDismissEdit, false); } } } // notify listeners of label edit state change OnLabelEditControlChanged(EventArgs.Empty); return fOkToContinue; }
private IVirtualTreeInPlaceControl DoLabelEdit( int absRow, int column, int message, bool explicitActivation, ref bool immediateActivation) { Debug.Assert(!explicitActivation || !immediateActivation); if (!GetAnyStyleFlag(VTCStyleFlags.LabelEditsMask)) { return null; } DismissLabelEdit(false, false); var nativeColumn = (myColumnPermutation != null) ? myColumnPermutation.GetNativeColumn(column) : column; var info = myTree.GetItemInfo(absRow, nativeColumn, false); var flags = info.Branch.Features; // UNDONE: Explicit Label Edits if (immediateActivation && (0 == (flags & (BranchFeatures.ImmediateMouseLabelEdits | BranchFeatures.ImmediateSelectionLabelEdits)))) { if (0 != (flags & BranchFeatures.DelayedLabelEdits)) { immediateActivation = false; } return null; } else if (explicitActivation && (0 == (flags & BranchFeatures.ExplicitLabelEdits))) { return null; } else if (!explicitActivation && !immediateActivation && 0 == (flags & BranchFeatures.DelayedLabelEdits)) { return null; } // Begin the label editing sequence by retrieving the data from // from the branch and filling in unsupplied default values. VirtualTreeLabelEditActivationStyles activationStyle; if (immediateActivation) { // Distinguish between mouse and non-mouse selection if the branch supports both if (0 == (flags & BranchFeatures.ImmediateMouseLabelEdits)) { activationStyle = VirtualTreeLabelEditActivationStyles.ImmediateSelection; } else if (GetStateFlag(VTCStateFlags.SelChangeFromMouse)) { activationStyle = VirtualTreeLabelEditActivationStyles.ImmediateMouse; } else { activationStyle = VirtualTreeLabelEditActivationStyles.ImmediateSelection; } } else if (explicitActivation) { activationStyle = VirtualTreeLabelEditActivationStyles.Explicit; } else { activationStyle = VirtualTreeLabelEditActivationStyles.Delayed; } var editData = info.Branch.BeginLabelEdit(info.Row, info.Column, activationStyle); if (!editData.IsValid) { return null; } else if (immediateActivation && editData.ActivationDeferred) { immediateActivation = false; return null; } var labelText = editData.AlternateText; var inPlaceEdit = editData.CustomInPlaceEdit; var maxTextLength = editData.MaxTextLength; if (labelText == null) { // Note: Don't compare to String.Empty. This allows the // user to return String.Empty to display an edit box with // nothing in it. labelText = info.Branch.GetText(info.Row, info.Column); } if (inPlaceEdit == null) // Alternate condition is not used. Without this check, // an invalid type will automatically throw a casting // exception in CreateEditInPlaceWindow, which is better // than silently ignoring the user setting. //|| !inPlaceEditType.IsSubclassOf(typeof(IVirtualTreeInPlaceControl))) { inPlaceEdit = typeof(VirtualTreeInPlaceEditControl); } ScrollIntoView(absRow, column); myEditColumn = column; myInPlaceControl = CreateEditInPlaceWindow(labelText, maxTextLength, column, message, inPlaceEdit); myCustomInPlaceCommit = editData.CustomCommit; var ctl = myInPlaceControl.InPlaceControl; // Set the colors of the in-place edit control myInPlaceControl.InPlaceControl.ForeColor = InPlaceEditForeColor; myInPlaceControl.InPlaceControl.BackColor = InPlaceEditBackColor; SetStateFlag(VTCStateFlags.LabelEditMask, false); SetStateFlag(VTCStateFlags.LabelEditActive, true); HideBubble(); myEditIndex = absRow; SetEditSize(); var invalidateEditItem = true; if (0 != (myInPlaceControl.Flags & VirtualTreeInPlaceControls.DrawItemText)) { SetStateFlag(VTCStateFlags.LabelEditTransparent, true); invalidateEditItem = false; } // Show the window and set focus to it. Do this after setting the // size so we don't get flicker. ctl.Show(); // Changing focus causes OnLostFocus for the currently focused control. // Ignore the case that this triggers a DismissLabelEdit. May happen if the edit control has // child controls, each of which dismisses on an OnLostFocus. SetStateFlag(VTCStateFlags.NoDismissEdit, true); try { ctl.Focus(); } finally { SetStateFlag(VTCStateFlags.NoDismissEdit, false); } if (invalidateEditItem) { InvalidateAreaForLabelEdit(absRow, column, ctl); } // Rescroll edit window myInPlaceControl.SelectAllText(); // notify listeners of label edit state change OnLabelEditControlChanged(EventArgs.Empty); return myInPlaceControl; }