Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Interactive window command handling #9334

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -129,7 +129,6 @@
<Compile Include="CommandIds.cs" />
<Compile Include="Guids.cs" />
<Compile Include="IVsInteractiveWindow2.cs" />
<Compile Include="VsInteractiveWindowPane.cs" />
<Compile Include="VsInteractiveWindowEditorFactoryService.cs" />
<Compile Include="InteractiveWindowPackage.cs" />
<Compile Include="IVsInteractiveWindow.cs" />
Expand Down
151 changes: 135 additions & 16 deletions src/InteractiveWindow/VisualStudio/VsInteractiveWindow.cs
Expand Up @@ -8,9 +8,13 @@
using System.Windows;
using System.Windows.Input;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Editor;
using Microsoft.VisualStudio.Imaging.Interop;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.TextManager.Interop;
using Microsoft.VisualStudio.Utilities;

namespace Microsoft.VisualStudio.InteractiveWindow.Shell
Expand All @@ -27,56 +31,171 @@ namespace Microsoft.VisualStudio.InteractiveWindow.Shell
/// on the interactive window.
/// </summary>
[Guid(Guids.InteractiveToolWindowIdString)]
internal sealed class VsInteractiveWindow : IOleCommandTarget, IVsInteractiveWindow2, IDisposable
internal sealed class VsInteractiveWindow : ToolWindowPane, IOleCommandTarget, IVsInteractiveWindow2
{
private readonly VsInteractiveWindowPane _windowPane;
// Keep in sync with Microsoft.VisualStudio.Editor.Implementation.EnableFindOptionDefinition.OptionName.
private const string EnableFindOptionName = "Enable Autonomous Find";

private readonly IComponentModel _componentModel;
private readonly IVsEditorAdaptersFactoryService _editorAdapters;
private readonly IInteractiveEvaluator _evaluator;

private IInteractiveWindow _window;
private IVsFindTarget _findTarget;
private IOleCommandTarget _commandTarget;
private IWpfTextViewHost _textViewHost;

internal VsInteractiveWindow(IComponentModel model, Guid providerId, int instanceId, string title, IInteractiveEvaluator evaluator, __VSCREATETOOLWIN creationFlags)
{
_windowPane = new VsInteractiveWindowPane(model, providerId, instanceId, title, evaluator, creationFlags);
}
_componentModel = model;
this.Caption = title;
_editorAdapters = _componentModel.GetService<IVsEditorAdaptersFactoryService>();
_evaluator = evaluator;

// The following calls this.OnCreate:
Guid clsId = this.ToolClsid;
Guid empty = Guid.Empty;
Guid typeId = providerId;
IVsWindowFrame frame;
var vsShell = (IVsUIShell)ServiceProvider.GlobalProvider.GetService(typeof(SVsUIShell));

// we don't pass __VSCREATETOOLWIN.CTW_fMultiInstance because multi instance panes are
// destroyed when closed. We are really multi instance but we don't want to be closed.

ErrorHandler.ThrowOnFailure(
vsShell.CreateToolWindow(
(uint)(__VSCREATETOOLWIN.CTW_fInitNew | __VSCREATETOOLWIN.CTW_fToolbarHost | creationFlags),
(uint)instanceId,
this.GetIVsWindowPane(),
ref clsId,
ref typeId,
ref empty,
null,
title,
null,
out frame));

void IDisposable.Dispose() => _windowPane.Dispose();
var guid = GetType().GUID;
ErrorHandler.ThrowOnFailure(frame.SetGuidProperty((int)__VSFPROPID.VSFPROPID_CmdUIGuid, ref guid));
this.Frame = frame;
}

int IOleCommandTarget.Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) =>
_windowPane.CommandTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
_commandTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);

int IOleCommandTarget.QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText) =>
_windowPane.CommandTarget.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
_commandTarget.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);

void IVsInteractiveWindow.SetLanguage(Guid languageServiceGuid, IContentType contentType) =>
InteractiveWindow.SetLanguage(languageServiceGuid, contentType);
_window.SetLanguage(languageServiceGuid, contentType);

void IVsInteractiveWindow.Show(bool focus)
{
var windowFrame = (IVsWindowFrame)WindowFrame;
var windowFrame = (IVsWindowFrame)this.Frame;
ErrorHandler.ThrowOnFailure(focus ? windowFrame.Show() : windowFrame.ShowNoActivate());

if (focus)
{
IInputElement input = InteractiveWindow.TextView as IInputElement;
IInputElement input = _window.TextView as IInputElement;
if (input != null)
{
Keyboard.Focus(input);
}
}
}

public IInteractiveWindow InteractiveWindow => _windowPane.InteractiveWindow;

public object WindowFrame => _windowPane.Frame;

ImageMoniker IVsInteractiveWindow2.BitmapImageMoniker
{
get
{
return _windowPane.BitmapImageMoniker;
return this.BitmapImageMoniker;
}

set
{
_windowPane.BitmapImageMoniker = value;
this.BitmapImageMoniker = value;
}
}

IInteractiveWindow IVsInteractiveWindow.InteractiveWindow => _window;

#region ToolWindowPane overrides

protected override void OnCreate()
{
_window = _componentModel.GetService<IInteractiveWindowFactoryService>().CreateWindow(_evaluator);
_window.SubmissionBufferAdded += SubmissionBufferAdded;
_textViewHost = _window.GetTextViewHost();
var textView = _textViewHost.TextView;
textView.Options.SetOptionValue(EnableFindOptionName, true);
var viewAdapter = _editorAdapters.GetViewAdapter(textView);
_findTarget = viewAdapter as IVsFindTarget;
_commandTarget = viewAdapter as IOleCommandTarget;
}

private void SubmissionBufferAdded(object sender, SubmissionBufferAddedEventArgs e)
{
GetToolbarHost().ForceUpdateUI();
}

protected override void OnClose()
{
_window.Close();
base.OnClose();
}

protected override void Dispose(bool disposing)
{
if (disposing)
{
if (_window != null)
{
_window.Dispose();
}
}
}

/// <summary>
/// This property returns the control that should be hosted in the Tool Window. It can be
/// either a FrameworkElement (for easy creation of tool windows hosting WPF content), or it
/// can be an object implementing one of the IVsUIWPFElement or IVsUIWin32Element
/// interfaces.
/// </summary>
public override object Content
{
get { return _textViewHost; }
set { }
}

object IVsInteractiveWindow2.WindowFrame
{
get
{
throw new NotImplementedException();
}
}

public override void OnToolWindowCreated()
{
Guid commandUiGuid = VSConstants.GUID_TextEditorFactory;
((IVsWindowFrame)Frame).SetGuidProperty((int)__VSFPROPID.VSFPROPID_InheritKeyBindings, ref commandUiGuid);

base.OnToolWindowCreated();

// add our toolbar which is defined in our VSCT file
var toolbarHost = GetToolbarHost();
Guid guidInteractiveCmdSet = Guids.InteractiveCommandSetId;
ErrorHandler.ThrowOnFailure(toolbarHost.AddToolbar(VSTWT_LOCATION.VSTWT_TOP, ref guidInteractiveCmdSet, (uint)MenuIds.InteractiveWindowToolbar));
}

#endregion

private IVsToolWindowToolbarHost GetToolbarHost()
{
var frame = (IVsWindowFrame)Frame;
object result;
ErrorHandler.ThrowOnFailure(frame.GetProperty((int)__VSFPROPID.VSFPROPID_ToolbarHost, out result));
return (IVsToolWindowToolbarHost)result;
}
}
}
142 changes: 0 additions & 142 deletions src/InteractiveWindow/VisualStudio/VsInteractiveWindowPane.cs

This file was deleted.