Skip to content

Commit

Permalink
Add support for drag-and-drop with cake and dll files
Browse files Browse the repository at this point in the history
  • Loading branch information
agc93 committed Feb 4, 2017
1 parent a1a11e9 commit 2763123
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/Cake.VisualStudio.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@
<Compile Include="Editor\SmartIndentProvider.cs" />
<Compile Include="Editor\SmartIndent.cs" />
<Compile Include="ContentType\CakeLanguageService.cs" />
<Compile Include="Editor\CakeDropHandler.cs" />
<Compile Include="Editor\CakeScriptDropHandler.cs" />
<Compile Include="Editor\CakeScriptDropHandlerProvider.cs" />
<Compile Include="Helpers\Constants.cs" />
<Compile Include="Helpers\Extensions.cs" />
<Compile Include="Helpers\PathHelpers.cs" />
Expand Down
31 changes: 31 additions & 0 deletions src/Editor/CakeDropHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.Text.Editor.DragDrop;

namespace Cake.VisualStudio.Editor
{
internal abstract class CakeDropHandler : IDropHandler
{
public DragDropPointerEffects HandleDragStarted(DragDropInfo dragDropInfo)
{
return DragDropPointerEffects.All;
}

public DragDropPointerEffects HandleDraggingOver(DragDropInfo dragDropInfo)
{
return DragDropPointerEffects.All;
}

public abstract DragDropPointerEffects HandleDataDropped(DragDropInfo dragDropInfo);

public abstract bool IsDropEnabled(DragDropInfo dragDropInfo);

public void HandleDragCanceled()
{

}
}
}
100 changes: 100 additions & 0 deletions src/Editor/CakeScriptDropHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Editor.DragDrop;

namespace Cake.VisualStudio.Editor
{
internal class CakeScriptDropHandler : CakeDropHandler
{
private readonly FileInfo _scriptFile;
private string _targetFileName;
private readonly IWpfTextView _textView;
private ITextDocument _document;
private readonly string[] _supportedFileExtensions = new[] {".cake", ".dll"};

public CakeScriptDropHandler(IWpfTextView textView, ITextDocument currentDocument)
{
_textView = textView;
_scriptFile = new FileInfo(currentDocument.FilePath);
_document = currentDocument;
}

public override DragDropPointerEffects HandleDataDropped(DragDropInfo dragDropInfo)
{
try
{
var relativePath = PackageUtilities.MakeRelative(_scriptFile.FullName, _targetFileName)
.Replace("\\", "/");
string insertString = null;
switch (Path.GetExtension(relativePath))
{
case ".cake":
insertString = $"#load \"{relativePath}\"";
break;
case ".dll":
insertString = $"#r \"{relativePath}\"";
break;
}

using (var edit = _textView.TextBuffer.CreateEdit())
{
edit.Insert(GetInsertPosition(), insertString + Environment.NewLine);
edit.Apply();
}
}
catch (Exception)
{
// ignored
}

return DragDropPointerEffects.Copy;
}

private int GetInsertPosition()
{
// need to improve logic here to find the first non-#load'ing line in the document.
return 0;
}

public override bool IsDropEnabled(DragDropInfo dragDropInfo)
{
_targetFileName = GetScriptFileName(dragDropInfo);
if (_targetFileName == null) return false;
var ext = Path.GetExtension(_targetFileName);
return _supportedFileExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase) &&
(File.Exists(_targetFileName) || Directory.Exists(_targetFileName));
}

private static string GetScriptFileName(DragDropInfo dragDropInfo)
{
var data = new DataObject(dragDropInfo.Data);

if (dragDropInfo.Data.GetDataPresent("FileDrop"))
{
var files = data.GetFileDropList();

if (files.Count == 1)
{
return files[0];
}
}
else if (dragDropInfo.Data.GetDataPresent("CF_VSSTGPROJECTITEMS") || dragDropInfo.Data.GetDataPresent("CF_VSREFPROJECTITEMS"))
{
return data.GetText();
}
else if (dragDropInfo.Data.GetDataPresent("MultiURL"))
{
return data.GetText();
}
return null;
}
}
}
42 changes: 42 additions & 0 deletions src/Editor/CakeScriptDropHandlerProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cake.VisualStudio.Classifier.Languages;
using Cake.VisualStudio.Helpers;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Editor.DragDrop;
using Microsoft.VisualStudio.Utilities;

namespace Cake.VisualStudio.Editor
{
[Export(typeof(IDropHandlerProvider))]
[DropFormat("CF_VSSTGPROJECTITEMS")]
[DropFormat("CF_VSREFPROJECTITEMS")]
[DropFormat("FileDrop")]
[Name("CakeDropHandler")]
[ContentType(Constants.CakeContentType)]
[Order(Before = "DefaultFileDropHandler")]
class CakeScriptDropHandlerProvider : IDropHandlerProvider
{
[Import]
ITextDocumentFactoryService TextDocumentFactoryService { get; set; }

public IDropHandler GetAssociatedDropHandler(IWpfTextView wpfTextView)
{
ITextDocument document;

if (TextDocumentFactoryService.TryGetTextDocument(wpfTextView.TextBuffer, out document))
{
return
wpfTextView.Properties.GetOrCreateSingletonProperty(
() => new CakeScriptDropHandler(wpfTextView, document));
}

return null;
}
}
}

0 comments on commit 2763123

Please sign in to comment.