#develop (short for SharpDevelop) is a free IDE for .NET programming languages.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

344 lines
11 KiB

// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using ICSharpCode.Build.Tasks;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.SharpDevelop.Gui
{
public class GacReferencePanel : UserControl, IReferencePanel
{
class ColumnSorter : System.Collections.IComparer
{
private int column = 0;
bool asc = true;
public int CurrentColumn
{
get
{
return column;
}
set
{
if(column == value) asc = !asc;
else column = value;
}
}
public int Compare(object x, object y)
{
ListViewItem rowA = (ListViewItem)x;
ListViewItem rowB = (ListViewItem)y;
int result = String.Compare(rowA.SubItems[CurrentColumn].Text, rowB.SubItems[CurrentColumn].Text);
if(asc) return result;
else return result * -1;
}
}
protected ListView listView;
CheckBox chooseSpecificVersionCheckBox;
TextBox filterTextBox;
ToolTip toolTip = new ToolTip();
ToolTip filterTextboxToolTip = new ToolTip();
ISelectReferenceDialog selectDialog;
ColumnSorter sorter;
BackgroundWorker worker;
List<ListViewItem> resultList = new List<ListViewItem>();
public GacReferencePanel(ISelectReferenceDialog selectDialog)
{
listView = new ListView();
sorter = new ColumnSorter();
listView.ListViewItemSorter = sorter;
this.selectDialog = selectDialog;
ColumnHeader referenceHeader = new ColumnHeader();
referenceHeader.Text = ResourceService.GetString("Dialog.SelectReferenceDialog.GacReferencePanel.ReferenceHeader");
referenceHeader.Width = 240;
listView.Columns.Add(referenceHeader);
listView.Sorting = SortOrder.Ascending;
ColumnHeader versionHeader = new ColumnHeader();
versionHeader.Text = ResourceService.GetString("Dialog.SelectReferenceDialog.GacReferencePanel.VersionHeader");
versionHeader.Width = 120;
listView.Columns.Add(versionHeader);
listView.View = View.Details;
listView.FullRowSelect = true;
listView.ItemActivate += delegate { AddReference(); };
listView.ColumnClick += new ColumnClickEventHandler(columnClick);
listView.Dock = DockStyle.Fill;
this.Dock = DockStyle.Fill;
this.Controls.Add(listView);
Panel upperPanel = new Panel { Dock = DockStyle.Top, Height = 20 };
chooseSpecificVersionCheckBox = new CheckBox();
chooseSpecificVersionCheckBox.Dock = DockStyle.Left;
chooseSpecificVersionCheckBox.AutoSize = true;
chooseSpecificVersionCheckBox.Text = StringParser.Parse("${res:Dialog.SelectReferenceDialog.GacReferencePanel.ChooseSpecificAssemblyVersion}");
chooseSpecificVersionCheckBox.CheckedChanged += delegate {
ResetList();
Search();
};
filterTextBox = new TextBox { Width = 150, Dock = DockStyle.Right };
filterTextboxToolTip.SetToolTip(filterTextBox, "Search by type name");
filterTextBox.TextChanged += delegate { Search(); };
IButtonControl defaultButton = null;
filterTextBox.Enter += delegate { defaultButton = ((Form)selectDialog).AcceptButton; ((Form)selectDialog).AcceptButton = null; };
filterTextBox.Leave += delegate { ((Form)selectDialog).AcceptButton = defaultButton; };
upperPanel.Controls.Add(chooseSpecificVersionCheckBox);
upperPanel.Controls.Add(filterTextBox);
this.Controls.Add(upperPanel);
PrintCache();
}
void ResetList()
{
listView.Items.Clear();
if (chooseSpecificVersionCheckBox.Checked)
listView.Items.AddRange(fullItemList);
else
listView.Items.AddRange(shortItemList);
}
void Search()
{
ResetList();
if (string.IsNullOrWhiteSpace(filterTextBox.Text))
return;
SearchItems(filterTextBox.Text);
listView.Items.Clear();
listView.Items.AddRange(resultList.ToArray());
}
void SearchItems(string text)
{
var searchList = listView.Items.OfType<ListViewItem>().ToList();
searchList.RemoveAll(item => item.Text.IndexOf(text, StringComparison.OrdinalIgnoreCase) < 0);
resultList = searchList;
}
protected override void Dispose(bool disposing)
{
if (disposing) {
// cancel the worker
if (worker != null && worker.IsBusy && !worker.CancellationPending)
worker.CancelAsync();
worker = null;
// clear all cached data
resultList = null;
selectDialog = null;
fullItemList = null;
}
base.Dispose(disposing);
}
void columnClick(object sender, ColumnClickEventArgs e)
{
if (e.Column < 2) {
sorter.CurrentColumn = e.Column;
listView.Sort();
}
}
public void AddReference()
{
foreach (ListViewItem item in listView.SelectedItems) {
string include = chooseSpecificVersionCheckBox.Checked ? item.Tag.ToString() : item.Text;
ReferenceProjectItem rpi = new ReferenceProjectItem(selectDialog.ConfigureProject, include);
string requiredFrameworkVersion;
if (chooseSpecificVersionCheckBox.Checked) {
if (KnownFrameworkAssemblies.TryGetRequiredFrameworkVersion(item.Tag.ToString(), out requiredFrameworkVersion)) {
rpi.SetMetadata("RequiredTargetFramework", requiredFrameworkVersion);
}
} else {
// find the lowest version of the assembly and use its RequiredTargetFramework
ListViewItem lowestVersion = item;
foreach (ListViewItem item2 in fullItemList) {
if (item2.Text == item.Text) {
if (new Version(item2.SubItems[1].Text) < ((DomAssemblyName)lowestVersion.Tag).Version) {
lowestVersion = item2;
}
}
}
if (KnownFrameworkAssemblies.TryGetRequiredFrameworkVersion(lowestVersion.Tag.ToString(), out requiredFrameworkVersion)) {
rpi.SetMetadata("RequiredTargetFramework", requiredFrameworkVersion);
}
}
selectDialog.AddReference(
item.Text, "Gac", rpi.Include,
rpi
);
}
}
ListViewItem[] fullItemList;
/// <summary>
/// Item list where older versions are filtered out.
/// </summary>
ListViewItem[] shortItemList;
void PrintCache()
{
IList<DomAssemblyName> cacheContent = GetCacheContent();
List<ListViewItem> itemList = new List<ListViewItem>();
// Create full item list
foreach (DomAssemblyName asm in cacheContent) {
ListViewItem item = new ListViewItem(new string[] {asm.ShortName, asm.Version.ToString()});
item.Tag = asm;
itemList.Add(item);
}
fullItemList = itemList.ToArray();
// Create short item list (without multiple versions)
itemList.Clear();
for (int i = 0; i < cacheContent.Count; i++) {
DomAssemblyName asm = cacheContent[i];
bool isDuplicate = false;
for (int j = 0; j < itemList.Count; j++) {
if (string.Equals(asm.ShortName, itemList[j].Text, StringComparison.OrdinalIgnoreCase)) {
itemList[j].SubItems[1].Text += "/" + asm.Version.ToString();
isDuplicate = true;
break;
}
}
if (!isDuplicate) {
ListViewItem item = new ListViewItem(new string[] {asm.ShortName, asm.Version.ToString()});
item.Tag = asm;
itemList.Add(item);
}
}
shortItemList = itemList.ToArray();
listView.Items.AddRange(shortItemList);
Thread resolveVersionsThread = new Thread(ResolveVersionsThread);
resolveVersionsThread.IsBackground = true;
resolveVersionsThread.Name = "resolveVersionsThread";
resolveVersionsThread.Priority = ThreadPriority.BelowNormal;
resolveVersionsThread.Start();
}
void ResolveVersionsThread()
{
try {
ResolveVersionsWorker();
//CreateReferenceToFrameworkTable();
} catch (Exception ex) {
MessageService.ShowException(ex);
}
}
void ResolveVersionsWorker()
{
MSBuildBasedProject project = selectDialog.ConfigureProject as MSBuildBasedProject;
if (project == null)
return;
List<ListViewItem> itemsToResolveVersion = new List<ListViewItem>();
List<ReferenceProjectItem> referenceItems = new List<ReferenceProjectItem>();
SD.MainThread.InvokeIfRequired(
delegate {
foreach (ListViewItem item in shortItemList) {
if (item.SubItems [1].Text.Contains("/")) {
itemsToResolveVersion.Add(item);
referenceItems.Add(new ReferenceProjectItem(project, item.Text));
}
}
});
SD.MSBuildEngine.ResolveAssemblyReferences(project, referenceItems.ToArray(), resolveOnlyAdditionalReferences: true, logErrorsToOutputPad: false);
SD.MainThread.InvokeAsyncAndForget(delegate {
if (IsDisposed) {
return;
}
for (int i = 0; i < itemsToResolveVersion.Count; i++) {
if (referenceItems [i].Version != null) {
itemsToResolveVersion [i].SubItems [1].Text = referenceItems [i].Version.ToString();
}
}
});
}
#if DEBUG
/// <summary>
/// run this method with a .net 3.5 and .net 4.0 project to generate the table above.
/// </summary>
void CreateReferenceToFrameworkTable()
{
LoggingService.Warn("Running CreateReferenceToFrameworkTable()");
MSBuildBasedProject project = selectDialog.ConfigureProject as MSBuildBasedProject;
if (project == null)
return;
var redistNameToRequiredFramework = new Dictionary<string, string> {
{ "Framework", null },
{ "Microsoft-Windows-CLRCoreComp", null },
{ "Microsoft.VisualStudio.Primary.Interop.Assemblies.8.0", null },
{ "Microsoft-WinFX-Runtime", "3.0" },
{ "Microsoft-Windows-CLRCoreComp.3.0", "3.0" },
{ "Microsoft-Windows-CLRCoreComp-v3.5", "3.5" },
{ "Microsoft-Windows-CLRCoreComp.4.0", "4.0" },
};
using (StreamWriter w = new StreamWriter("c:\\temp\\references.txt")) {
List<ReferenceProjectItem> referenceItems = new List<ReferenceProjectItem>();
SD.MainThread.InvokeIfRequired(
delegate {
foreach (ListViewItem item in fullItemList) {
referenceItems.Add(new ReferenceProjectItem(project, item.Tag.ToString()));
}
});
SD.MSBuildEngine.ResolveAssemblyReferences(project, referenceItems.ToArray(), resolveOnlyAdditionalReferences: true, logErrorsToOutputPad: false);
foreach (ReferenceProjectItem rpi in referenceItems) {
if (string.IsNullOrEmpty(rpi.Redist)) continue;
if (!redistNameToRequiredFramework.ContainsKey(rpi.Redist)) {
LoggingService.Error("unknown redist: " + rpi.Redist);
} else if (redistNameToRequiredFramework[rpi.Redist] != null) {
w.Write("\t\t\t{ \"");
w.Write(rpi.Include);
w.Write("\", \"");
w.Write(redistNameToRequiredFramework[rpi.Redist]);
w.WriteLine("\" },");
}
}
}
}
#endif
protected virtual IList<DomAssemblyName> GetCacheContent()
{
return SD.GlobalAssemblyCache.Assemblies
.Where(name => !name.ShortName.EndsWith(".resources", StringComparison.OrdinalIgnoreCase))
.ToList();
}
}
}