Skip to content

Commit

Permalink
"Collapse" command will now consider only active view.
Browse files Browse the repository at this point in the history
  • Loading branch information
triforcely committed Oct 5, 2017
1 parent 011a8f1 commit 72f6a76
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 50 deletions.
99 changes: 53 additions & 46 deletions CollapseLevel/CollapseLevel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Outlining;
using Microsoft.VisualStudio.TextManager.Interop;
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
Expand Down Expand Up @@ -44,14 +44,19 @@ internal sealed class CollapseLevel
/// </summary>
private readonly Package package;

// Will keep value of last custom level so input prompt can be populated with last value.
/// <summary>
/// Text manager to get information about active views.
/// </summary>
private readonly IVsTextManager textManager;

/// <summary>
/// Initializes a new instance of the <see cref="CollapseLevel"/> class.
/// Adds our command handlers for menu (commands must exist in the command table file)
/// </summary>
private CollapseLevel(Package package)
private CollapseLevel(Package package, IVsTextManager textManager)
{
this.package = package ?? throw new ArgumentNullException("package");
this.textManager = textManager;

OleMenuCommandService commandService = this.ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if (commandService != null)
Expand Down Expand Up @@ -107,75 +112,77 @@ private IVsStatusbar StatusBar
/// Initializes the singleton instance of the command.
/// </summary>
/// <param name="package">Owner package, not null.</param>
public static void Initialize(Package package)
public static void Initialize(Package package, IVsTextManager textManager)
{
Instance = new CollapseLevel(package);
Instance = new CollapseLevel(package, textManager);
}

/// <summary>
/// Walk through all the regions, calculate their levels and collapse all regions where n = level +1.
/// </summary>
private void Collapse(int level)
{
var componentModel = this.ServiceProvider.GetService(typeof(SComponentModel)) as IComponentModel;
var tv = TextViewRegistry.GetActiveTextView(this.textManager);

foreach (ITextView tv in TextViewRegistry.GetExistingViews()) // Collapse is performed on all open documents in current state of extension.
if (tv == null)
return;

var componentModel = this.ServiceProvider.GetService(typeof(SCompon`entModel)) as IComponentModel;

if (componentModel != null)
{
if (componentModel != null)
{
var outliningManagerService = componentModel.GetService<IOutliningManagerService>();
var outliningManagerService = componentModel.GetService<IOutliningManagerService>();

if (outliningManagerService != null)
OutliningManager = outliningManagerService.GetOutliningManager(tv);
}
if (outliningManagerService != null)
OutliningManager = outliningManagerService.GetOutliningManager(tv);
}

if (OutliningManager != null)
if (OutliningManager != null)
{
try
{
try
{
var length = tv.TextSnapshot.Length;
var textViewSpan = new SnapshotSpan(tv.TextSnapshot, 0, length);
var regions = OutliningManager.GetAllRegions(textViewSpan);
var length = tv.TextSnapshot.Length;
var textViewSpan = new SnapshotSpan(tv.TextSnapshot, 0, length);
var regions = OutliningManager.GetAllRegions(textViewSpan);

Dictionary<ICollapsible, int> regionCount = new Dictionary<ICollapsible, int>();
Dictionary<ICollapsible, int> regionCount = new Dictionary<ICollapsible, int>();

foreach (var region in regions)
{
var extent = region.Extent;
var span = extent.GetSpan(tv.TextSnapshot);
foreach (var region in regions)
{
var extent = region.Extent;
var span = extent.GetSpan(tv.TextSnapshot);

foreach (var compareTo in regions)
{
if (compareTo.Equals(region))
continue;
foreach (var compareTo in regions)
{
if (compareTo.Equals(region))
continue;

if (!regionCount.ContainsKey(region))
regionCount[region] = 1;
if (!regionCount.ContainsKey(region))
regionCount[region] = 1;

var compareToSpan = compareTo.Extent.GetSpan(tv.TextSnapshot);
var regionSpan = region.Extent.GetSpan(tv.TextSnapshot);
var compareToSpan = compareTo.Extent.GetSpan(tv.TextSnapshot);
var regionSpan = region.Extent.GetSpan(tv.TextSnapshot);

if (compareToSpan.Contains(regionSpan))
{
regionCount[region] = regionCount[region] + 1;
}
if (compareToSpan.Contains(regionSpan))
{
regionCount[region] = regionCount[region] + 1;
}
}
}

OutliningManager.ExpandAll(textViewSpan, (y) => (true));
OutliningManager.ExpandAll(textViewSpan, (y) => (true));

foreach (var pair in regionCount)
foreach (var pair in regionCount)
{
if (pair.Value == level)
{
if (pair.Value == level)
{
OutliningManager.TryCollapse(pair.Key);
}
OutliningManager.TryCollapse(pair.Key);
}
}
catch (ObjectDisposedException)
{
// TODO Investigate, happened once while testing some early version.
}
}
catch (ObjectDisposedException)
{
// TODO Investigate, happened once while testing some early version.
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions CollapseLevel/CollapseLevel.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@
<HintPath>..\packages\Microsoft.VisualStudio.CoreUtility.14.3.25407\lib\net45\Microsoft.VisualStudio.CoreUtility.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.Editor, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.VisualStudio.Editor.14.0.23205\lib\net45\Microsoft.VisualStudio.Editor.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.Imaging, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.VisualStudio.Imaging.14.3.25407\lib\net45\Microsoft.VisualStudio.Imaging.dll</HintPath>
<Private>True</Private>
Expand Down
9 changes: 7 additions & 2 deletions CollapseLevel/CollapseLevelPackage.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Microsoft.VisualStudio.Shell;
using EnvDTE;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.TextManager.Interop;
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
Expand All @@ -19,7 +21,10 @@ public CollapseLevelPackage()

protected override void Initialize()
{
CollapseLevel.Initialize(this);
DTE dte = (DTE)base.GetService(typeof(DTE));
var textManager = (IVsTextManager)base.GetService(typeof(SVsTextManager));

CollapseLevel.Initialize(this, textManager);
base.Initialize();
}
}
Expand Down
33 changes: 32 additions & 1 deletion CollapseLevel/Core/TextViewRegistry.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Editor;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.TextManager.Interop;
using Microsoft.VisualStudio.Utilities;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
Expand All @@ -16,6 +19,34 @@ public class TextViewRegistry : IWpfTextViewCreationListener
{
private static List<IWpfTextView> textViews = new List<IWpfTextView>();

/// <summary>
/// Gets the active IWpfTextView, if one exists. <see href="https://github.com/CodeConnect/gistify/blob/master/CodeConnect.Gistify.Extension/TextManagerExtensions.cs"/>
/// </summary>
/// <returns>The active IWpfTextView, or null if no such IWpfTextView exists.</returns>
public static IWpfTextView GetActiveTextView(IVsTextManager textManager)
{
IWpfTextView view = null;
IVsTextView vTextView = null;

textManager.GetActiveView(
fMustHaveFocus: 1
, pBuffer: null
, ppView: out vTextView);

IVsUserData userData = vTextView as IVsUserData;
if (null != userData)
{
IWpfTextViewHost viewHost;
object holder;
Guid guidViewHost = DefGuidList.guidIWpfTextViewHost;
userData.GetData(ref guidViewHost, out holder);
viewHost = (IWpfTextViewHost)holder;
view = viewHost.TextView;
}

return view;
}

public static IEnumerable<IWpfTextView> GetExistingViews()
{
return textViews.Where(p => !p.IsClosed); // Return only open views.
Expand Down
1 change: 1 addition & 0 deletions CollapseLevel/packages.config
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.VisualStudio.CoreUtility" version="14.3.25407" targetFramework="net46" />
<package id="Microsoft.VisualStudio.Editor" version="14.0.23205" targetFramework="net46" />
<package id="Microsoft.VisualStudio.Imaging" version="14.3.25407" targetFramework="net46" />
<package id="Microsoft.VisualStudio.OLE.Interop" version="7.10.6070" targetFramework="net46" />
<package id="Microsoft.VisualStudio.Shell.14.0" version="14.3.25407" targetFramework="net46" />
Expand Down
2 changes: 1 addition & 1 deletion CollapseLevel/source.extension.vsixmanifest
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
<Metadata>
<Identity Id="CollapseLevel.Michał Wilski.9739fb10-2beb-4d62-b127-ab7b7646a060" Version="2.0.1" Language="en-US" Publisher="Michał Wilski" />
<Identity Id="CollapseLevel.Michał Wilski.9739fb10-2beb-4d62-b127-ab7b7646a060" Version="2.0.2" Language="en-US" Publisher="Michał Wilski" />
<DisplayName>Collapse Level</DisplayName>
<Description>Collapse your structures using simple commands. Works for programming languages, markup languages and data interchange formats - basically everything that you can manually fold in Visual Studio. </Description>
<MoreInfo>https://marketplace.visualstudio.com/items?itemName=mwilski.CollapseLevel</MoreInfo>
Expand Down

0 comments on commit 72f6a76

Please sign in to comment.