Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 70 additions & 51 deletions MultiEdit/MultiPointEditCommandFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ class MultiPointEditCommandFilter : IOleCommandTarget
private IWpfTextView m_textView;
private IAdornmentLayer m_adornmentLayer;
private List<ITrackingPoint> m_trackList;
private CaretPosition lastCaretPosition = new CaretPosition();
private CaretPosition m_lastCaretPosition = new CaretPosition();
private DTE2 m_dte;
private Dictionary<string, int> positionHash = new Dictionary<string, int>();
public MultiPointEditCommandFilter(IWpfTextView tv)
{
m_textView = tv;
m_adornmentLayer = tv.GetAdornmentLayer("MultiEditLayer");
m_trackList = new List<ITrackingPoint>();
lastCaretPosition = m_textView.Caret.Position;
m_lastCaretPosition = m_textView.Caret.Position;
m_textView.LayoutChanged += m_textView_LayoutChanged;
m_dte = ServiceProvider.GlobalProvider.GetService(typeof(DTE)) as DTE2;
}
Expand All @@ -43,6 +43,8 @@ public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pv
{
Debug.WriteLine(nCmdID);

bool trackListNonEmpty = m_trackList.Count > 0;
bool performSyncedOp = false;
if (pguidCmdGroup == typeof(VSConstants.VSStd2KCmdID).GUID)
{
switch (nCmdID)
Expand All @@ -64,14 +66,32 @@ public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pv
case ((uint)VSConstants.VSStd2KCmdID.PASTEASHTML):
case ((uint)VSConstants.VSStd2KCmdID.BOL):
case ((uint)VSConstants.VSStd2KCmdID.EOL):
case ((uint)VSConstants.VSStd2KCmdID.RETURN):
case ((uint)VSConstants.VSStd2KCmdID.BACKTAB):
case ((uint)VSConstants.VSStd2KCmdID.RETURN):
case ((uint)VSConstants.VSStd2KCmdID.BACKTAB):
case ((uint)VSConstants.VSStd2KCmdID.WORDPREV):
case ((uint)VSConstants.VSStd2KCmdID.WORDNEXT):


if (m_trackList.Count > 0)
return SyncedOperation(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
performSyncedOp = trackListNonEmpty;
break;
case ((uint)VSConstants.VSStd2KCmdID.UP_EXT_COL):
case ((uint)VSConstants.VSStd2KCmdID.DOWN_EXT_COL):
// Allow expanding track list vertically but only if there isn't any prior
// horizontal selection. This effectively means that if the block selection is
// started with vertical extension we will use Multi Edit, but if it is started
// with horizontal extension we will use the old-school behavior.
performSyncedOp = m_textView.Selection.SelectedSpans.All(span => span.Length == 0);
break;
case ((uint)VSConstants.VSStd2KCmdID.LEFT_EXT):
case ((uint)VSConstants.VSStd2KCmdID.RIGHT_EXT):
case ((uint)VSConstants.VSStd2KCmdID.CANCEL):
case ((uint)VSConstants.VSStd2KCmdID.LEFT_EXT_COL):
case ((uint)VSConstants.VSStd2KCmdID.RIGHT_EXT_COL):
if (trackListNonEmpty)
{
// Break out of the Multi Edit mode when (unsupported) horizontal
// selection or ESC is used.
ClearSyncPoints();
RedrawScreen();
}
break;
default:
break;
Expand All @@ -83,50 +103,44 @@ public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pv
{

case ((uint)VSConstants.VSStd97CmdID.Delete):
case ((uint)VSConstants.VSStd97CmdID.Paste):
if (m_trackList.Count > 0)
return SyncedOperation(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
case ((uint)VSConstants.VSStd97CmdID.Paste):
performSyncedOp = trackListNonEmpty;
break;
default:
break;
}
}


switch (nCmdID)
{

// When ESC is used, cancel the Multi Edit mode
case ((uint)VSConstants.VSStd2KCmdID.CANCEL):
ClearSyncPoints();
RedrawScreen();
break;
default:
break;
}

return NextTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
if (performSyncedOp)
return SyncedOperation(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
else
return NextTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
}

private int SyncedOperation(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
{

{
ITextCaret caret = m_textView.Caret;

if (m_trackList.Count == 0)
AddSyncPoint(caret.Position);

var tempTrackList = m_trackList;
m_trackList = new List<ITrackingPoint>();

SnapshotPoint snapPoint = tempTrackList[0].GetPoint(m_textView.TextSnapshot);
int result = 0;

m_dte.UndoContext.Open("Multi-point edit");

for (int i = 0; i < tempTrackList.Count; i++)
{
snapPoint = tempTrackList[i].GetPoint(m_textView.TextSnapshot);
SnapshotPoint snapPoint = tempTrackList[i].GetPoint(m_textView.TextSnapshot);
caret.MoveTo(snapPoint);
Debug.Print("Caret #" + i + " pos : " + caret.Position);
result = NextTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
AddSyncPoint(m_textView.Caret.Position);
if (pguidCmdGroup == typeof(VSConstants.VSStd2KCmdID).GUID &&
(nCmdID == (uint)VSConstants.VSStd2KCmdID.UP_EXT_COL || nCmdID == (uint)VSConstants.VSStd2KCmdID.DOWN_EXT_COL))
AddSyncPointsFromSelections();
else
AddSyncPoint(m_textView.Caret.Position);
}

m_dte.UndoContext.Close();
Expand All @@ -151,13 +165,13 @@ private void RedrawScreen()
var curPosition = trackPoint.GetPosition(m_textView.TextSnapshot);
IncrementCount(positionHash, curPosition.ToString());
if (positionHash[curPosition.ToString()] > 1)
continue;
continue;
DrawSingleSyncPoint(trackPoint);
newTrackList.Add(trackPoint);
}

m_trackList = newTrackList;

}

private void IncrementCount(Dictionary<string, int> someDictionary, string id)
Expand Down Expand Up @@ -195,11 +209,6 @@ private void DrawSingleSyncPoint(ITrackingPoint trackPoint)

}

private void RemoveIntersectedCarets()
{

}

private void AddSyncPoint(CaretPosition caretPosition)
{
CaretPosition curPosition = caretPosition;
Expand All @@ -209,7 +218,6 @@ private void AddSyncPoint(CaretPosition caretPosition)
// Check if the bounds are valid

if (curTrackPoint.GetPosition(m_textView.TextSnapshot) >= 0)

m_trackList.Add(curTrackPoint);
else
{
Expand All @@ -222,13 +230,19 @@ private void AddSyncPoint(CaretPosition caretPosition)
m_textView.Caret.MoveTo(curTrackPoint.GetPoint(m_textView.TextSnapshot));
}
}


private void AddSyncPoint(int position)
{
m_trackList.Add(m_textView.TextSnapshot.CreateTrackingPoint(Math.Max(position, 0), PointTrackingMode.Positive));
}

private void AddSyncPointsFromSelections()
{
foreach (var span in m_textView.Selection.SelectedSpans)
AddSyncPoint(span.Start.Position);
m_textView.Selection.Clear();
}

public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
{
if (pguidCmdGroup == typeof(VSConstants.VSStd2KCmdID).GUID)
Expand All @@ -239,6 +253,8 @@ public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, Int
{
case ((uint)VSConstants.VSStd2KCmdID.TYPECHAR):
case ((uint)VSConstants.VSStd2KCmdID.BACKSPACE):
case ((uint)VSConstants.VSStd2KCmdID.DELETEWORDRIGHT):
case ((uint)VSConstants.VSStd2KCmdID.DELETEWORDLEFT):
case ((uint)VSConstants.VSStd2KCmdID.TAB):
case ((uint)VSConstants.VSStd2KCmdID.LEFT):
case ((uint)VSConstants.VSStd2KCmdID.RIGHT):
Expand All @@ -253,7 +269,16 @@ public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, Int
case ((uint)VSConstants.VSStd2KCmdID.BOL):
case ((uint)VSConstants.VSStd2KCmdID.EOL):
case ((uint)VSConstants.VSStd2KCmdID.RETURN):
case ((uint)VSConstants.VSStd2KCmdID.BACKTAB):
case ((uint)VSConstants.VSStd2KCmdID.BACKTAB):
case ((uint)VSConstants.VSStd2KCmdID.WORDPREV):
case ((uint)VSConstants.VSStd2KCmdID.WORDNEXT):
case ((uint)VSConstants.VSStd2KCmdID.UP_EXT_COL):
case ((uint)VSConstants.VSStd2KCmdID.DOWN_EXT_COL):
case ((uint)VSConstants.VSStd2KCmdID.LEFT_EXT):
case ((uint)VSConstants.VSStd2KCmdID.RIGHT_EXT):
case ((uint)VSConstants.VSStd2KCmdID.CANCEL):
case ((uint)VSConstants.VSStd2KCmdID.LEFT_EXT_COL):
case ((uint)VSConstants.VSStd2KCmdID.RIGHT_EXT_COL):
prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED);
return VSConstants.S_OK;
}
Expand All @@ -270,27 +295,21 @@ public void HandleClick(bool addCursor)
if (m_textView.Selection.SelectedSpans.Count == 1)
{
if (m_trackList.Count == 0)
AddSyncPoint(lastCaretPosition);
AddSyncPoint(m_lastCaretPosition);

AddSyncPoint(m_textView.Caret.Position);
RedrawScreen();
}
else
{
foreach (var span in m_textView.Selection.SelectedSpans)
AddSyncPoint(span.Start.Position);

m_textView.Selection.Clear();
RedrawScreen();
}
AddSyncPointsFromSelections();
RedrawScreen();
}
else if (m_trackList.Any())
{
ClearSyncPoints();
RedrawScreen();
}

lastCaretPosition = m_textView.Caret.Position;
m_lastCaretPosition = m_textView.Caret.Position;
}

internal bool Added { get; set; }
Expand Down