Пример #1
0
        /// <summary>
        /// Determines whether two <see cref="DragDropInfo"/> objects have the same settings.
        /// </summary>
        /// <param name="obj">The object to compare.</param>
        /// <returns><c>true</c> if the two objects have the same settings, otherwise <c>false</c>.</returns>
        public override bool Equals(object obj)
        {
            DragDropInfo other = obj as DragDropInfo;

            if (obj != null)
            {
                return(Location == other.Location && KeyStates == other.KeyStates && Data == other.Data &&
                       AllowedEffects == other.AllowedEffects && IsInternal == other.IsInternal && Source == other.Source &&
                       VirtualBufferPosition == other.VirtualBufferPosition);
            }
            else
            {
                return(false);
            }
        }
Пример #2
0
        /// <summary>
        /// Determines whether the handler can accept data for a drag and drop operation.
        /// </summary>
        /// <param name="dragDropInfo">
        /// Information about the drag and drop operation.
        /// </param>
        /// <returns><c>true</c> if the handler can accept data now, otherwise <c>false</c>.</returns>
        /// <remarks>
        /// <para>This method is used by the editor to check whether the drop handler can accept data
        /// after it has been designated to handle a drag and drop operation. For example,
        /// the drop handler may be able to handle data only if the view is not read-only.
        /// The implementation of this method would check the read-only status of the view.</para>
        /// <para>If one drop handler returns <c>false</c>,
        /// another drop handler might be used to handle the drop operation, even if
        /// the ordering of <see cref="IDropHandler"/> objects dictates otherwise.</para>
        /// </remarks>
        public virtual bool IsDropEnabled(DragDropInfo dragDropInfo)
        {
            if (dragDropInfo == null)
            {
                throw new ArgumentNullException(nameof(dragDropInfo));
            }

            //ensure the source allows either move or copy operation
            if (!(
                    (dragDropInfo.AllowedEffects & NSDragOperation.Copy) == NSDragOperation.Copy ||
                    (dragDropInfo.AllowedEffects & NSDragOperation.Move) == NSDragOperation.Move))
            {
                return(false);
            }

            //only allow dropping when the view is not read-only
            return(!_cocoaTextView.Options.GetOptionValue <bool>(DefaultTextViewOptions.ViewProhibitUserInputId));
        }
Пример #3
0
        /// <summary>
        /// Determines what drag &amp; drop effect should be displayed to the user based on the state of the operation.
        /// </summary>
        protected virtual DragDropPointerEffects GetDragDropEffect(DragDropInfo dragDropInfo)
        {
            if (dragDropInfo == null)
            {
                throw new ArgumentNullException(nameof(dragDropInfo));
            }

            VirtualSnapshotPoint dropPoint = dragDropInfo.VirtualBufferPosition.TranslateTo(_cocoaTextView.TextSnapshot);

            //if an external drop is being performed on a read-only region, then disallow it
            if (_cocoaTextView.TextBuffer.IsReadOnly(dropPoint.Position))
            {
                return(DragDropPointerEffects.None);
            }

            //determine mode based on user key pressings
            if (((dragDropInfo.AllowedEffects & NSDragOperation.Copy) == NSDragOperation.Copy) && ((dragDropInfo.KeyStates & NSEventModifierMask.AlternateKeyMask) == NSEventModifierMask.AlternateKeyMask))
            {
                return(DragDropPointerEffects.Copy | DragDropPointerEffects.Track);
            }

            //if (((dragDropInfo.AllowedEffects & NSDragOperation.Move) == NSDragOperation.Move) && ((dragDropInfo.KeyStates & NSEventModifierMask.ShiftKey) == NSEventModifierMask.ShiftKey))
            //    return DragDropPointerEffects.Move | DragDropPointerEffects.Track;

            //if control flow gets here, then the user's key pressings must be ignored in order to continue the drag/drop operation because
            //the combination of the user's key pressings with the allowed drag/drop effects is invalid.

            //if move mode is allowed, set move effect
            if ((dragDropInfo.AllowedEffects & NSDragOperation.Move) == NSDragOperation.Move)
            {
                return(DragDropPointerEffects.Move | DragDropPointerEffects.Track);
            }

            //if copy mode is allowed, then indicate copy mode
            if ((dragDropInfo.AllowedEffects & NSDragOperation.Copy) == NSDragOperation.Copy)
            {
                return(DragDropPointerEffects.Copy | DragDropPointerEffects.Track);
            }

            return(DragDropPointerEffects.None);
        }
Пример #4
0
 /// <summary>
 /// Indicates that the drag and drop operation is in progress.
 /// </summary>
 /// <param name="dragDropInfo">
 /// Information about the drag and drop operation in progress.
 /// </param>
 /// <returns>
 /// A <see cref="DragDropPointerEffects"/> for the current operation. For example, this can be used to
 /// indicate a copy operation when the CTRL key is down.
 /// </returns>
 /// <remarks>This method is called continuously while the user is dragging the mouse over the text editor during
 /// a drag and drop operation. It can be used to
 /// draw additional information next to the mouse cursor as a preview of the text after the drop operation.
 /// </remarks>
 public virtual DragDropPointerEffects HandleDraggingOver(DragDropInfo dragDropInfo)
 {
     return(this.GetDragDropEffect(dragDropInfo));
 }
Пример #5
0
        /// <summary>
        /// This method selects the text at the end of the drop operation.
        /// </summary>
        /// <remarks>
        /// This method will only be called if the drop of data resulted in an <see cref="DragDropEffects"/> other than DragDropEffects.None.
        /// </remarks>
        /// <param name="insertionPoint">The position at which data was inserted.</param>
        /// <param name="dataLength">The length of the data inserted in the buffer.</param>
        /// <param name="virtualSpaceLength">The length of whitespace inserted in the buffer to fill the gap between the closest buffer position
        ///  and the position at which data was dropped. This value will be non-zero only if data was dropped into virtual space.</param>
        /// <param name="dragDropInfo">The <see cref="DragDropInfo"/> class containing information about the drop.</param>
        /// <param name="reverse">True if the existing selection prior to the drop was reversed.</param>
        protected virtual void SelectText(SnapshotPoint insertionPoint, int dataLength, DragDropInfo dragDropInfo, bool reverse)
        {
            if (insertionPoint == null)
            {
                throw new ArgumentNullException(nameof(insertionPoint));
            }
            if (dragDropInfo == null)
            {
                throw new ArgumentNullException(nameof(dragDropInfo));
            }

            VirtualSnapshotPoint anchorPoint = new VirtualSnapshotPoint(insertionPoint);
            VirtualSnapshotPoint activePoint = new VirtualSnapshotPoint(insertionPoint.Add(dataLength));

            if (dragDropInfo.IsInternal && reverse)
            {
                _editorOperations.SelectAndMoveCaret(activePoint, anchorPoint, TextSelectionMode.Stream);
            }
            else
            {
                _editorOperations.SelectAndMoveCaret(anchorPoint, activePoint, TextSelectionMode.Stream);
            }
        }
Пример #6
0
 /// <summary>
 /// This method is called after the edits are made to the buffer to perform any necessary post edit actions.
 /// </summary>
 /// <param name="successfulEdit">If true, the edits performed on the buffer were successful, otherwise, the edits failed.</param>
 /// <param name="dragDropInfo">The <see cref="DragDropInfo"/> holding information about the currently ongoing drag/drop operation.</param>
 protected abstract void PerformPostEditActions(DragDropInfo dragDropInfo, bool successfulEdit);
Пример #7
0
 /// <summary>
 /// This method is called before edits are made to the buffer to perform any necessary pre edit actions.
 /// </summary>
 /// <param name="dragDropInfo">The <see cref="DragDropInfo"/> holding information about the currently ongoing drag/drop operation.</param>
 protected abstract void PerformPreEditActions(DragDropInfo dragDropInfo);
Пример #8
0
 /// <summary>
 /// This method extracts the text of an <see cref="DragDropInfo"/> object.
 /// </summary>
 protected abstract string ExtractText(DragDropInfo dragDropInfo);
Пример #9
0
        /// <summary>
        /// Indicates that the drag and drop operation has completed, and that the final tasks, if any, should be performed now.
        /// </summary>
        /// <param name="dragDropInfo">
        /// Information about the drag and drop operation in progress.
        /// </param>
        /// <returns>
        /// The drag and drop effects of this drop operation. For example, if the drop operation has moved data,
        /// DragDropPointerEffects.Move should be returned.
        /// </returns>
        /// <remarks>This method is called when the user drops the data onto the editor.
        /// This marks the end of a drag and drop operation.
        /// The <see cref="IDropHandler"/> is expected to perform the final tasks of the operation.
        /// </remarks>
        public virtual DragDropPointerEffects HandleDataDropped(DragDropInfo dragDropInfo)
        {
            if (dragDropInfo == null)
            {
                throw new ArgumentNullException(nameof(dragDropInfo));
            }

            ITextSelection selection = _cocoaTextView.Selection;
            //keeps track of the result of this operation
            DragDropPointerEffects result = DragDropPointerEffects.None;
            //tracks the location at which the data was dropped
            VirtualSnapshotPoint dropLocation = dragDropInfo.VirtualBufferPosition;
            //convert the drag/drop data to text
            string dragDropText  = this.ExtractText(dragDropInfo);
            bool   isReversed    = selection.IsReversed;
            bool   copyRequested = (dragDropInfo.KeyStates & NSEventModifierMask.AlternateKeyMask) == NSEventModifierMask.AlternateKeyMask;
            bool   copyAllowed   = (dragDropInfo.AllowedEffects & NSDragOperation.Copy) == NSDragOperation.Copy;

            ITextSnapshot preEditSnapshot = _cocoaTextView.TextSnapshot;

            // track the point where the data will be inserted
            ITrackingPoint insertionPoint = preEditSnapshot.CreateTrackingPoint(dropLocation.Position, PointTrackingMode.Negative);

            // track the currently selected spans before any edits are performed on the buffer
            List <ITrackingSpan> selectionSpans = new List <ITrackingSpan>();

            foreach (SnapshotSpan selectedSpan in selection.SelectedSpans)
            {
                selectionSpans.Add(preEditSnapshot.CreateTrackingSpan(selectedSpan, SpanTrackingMode.EdgeExclusive));
            }

            // perform any necessary pre edit actions
            this.PerformPreEditActions(dragDropInfo);

            // clear selection before data operations
            if (!selection.IsEmpty)
            {
                selection.Clear();
            }

            // a reference to the snapshot resulting from the edits
            bool successfulEdit = false;

            // if the data is being dropped in virtual space, calculate how many whitespace characters will be inserted
            // to fill the gap between the dropped point and the closest buffer position
            int virtualSpaceLength = 0;

            if (dragDropInfo.VirtualBufferPosition.IsInVirtualSpace)
            {
                virtualSpaceLength = _editorOperations.GetWhitespaceForVirtualSpace(dragDropInfo.VirtualBufferPosition).Length;
            }

            if (copyRequested && copyAllowed)
            {
                //copy the data by inserting it in the buffer
                successfulEdit = this.InsertText(dropLocation, dragDropText);
                if (successfulEdit)
                {
                    result = DragDropPointerEffects.Copy;
                }
            }
            else
            {
                //the data needs to be moved
                if (dragDropInfo.IsInternal)
                {
                    //delete the existing selection, and add the data to the new location
                    successfulEdit = this.MoveText(dropLocation, selectionSpans, dragDropText);
                }
                else
                {
                    //the drag is not from this text view, just insert the data at dropLocation
                    successfulEdit = this.InsertText(dropLocation, dragDropText);
                }

                //set the pointer effect to move if the edit was successful since that implies that the data was moved successfully
                if (successfulEdit)
                {
                    result = DragDropPointerEffects.Move;
                }
            }

            // finally select the newly inserted data if the operation was successful
            if (result != DragDropPointerEffects.None)
            {
                SnapshotPoint textInsertionPoint = insertionPoint.GetPoint(_cocoaTextView.TextSnapshot);

                // if the data was inserted in virtual space, offset the selection's anchor point by the whitespace that was inserted
                // in virtual space
                if (virtualSpaceLength != 0)
                {
                    textInsertionPoint = textInsertionPoint.Add(virtualSpaceLength);
                }

                this.SelectText(textInsertionPoint, dragDropText.Length, dragDropInfo, isReversed);
            }

            // perform any post edit actions as necessary
            this.PerformPostEditActions(dragDropInfo, successfulEdit);

            return(result);
        }