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.
193 lines
7.1 KiB
193 lines
7.1 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.IO; |
|
using ICSharpCode.Core; |
|
using ICSharpCode.SharpDevelop.Gui; |
|
|
|
namespace ICSharpCode.SharpDevelop |
|
{ |
|
/// <summary> |
|
/// This class handles the installed display bindings |
|
/// and provides a simple access point to these bindings. |
|
/// </summary> |
|
public static class DisplayBindingService |
|
{ |
|
const string displayBindingPath = "/SharpDevelop/Workbench/DisplayBindings"; |
|
|
|
static Properties displayBindingServiceProperties; |
|
|
|
static List<DisplayBindingDescriptor> bindings; |
|
static List<ExternalProcessDisplayBinding> externalProcessDisplayBindings = new List<ExternalProcessDisplayBinding>(); |
|
|
|
internal static void InitializeService() |
|
{ |
|
bindings = AddInTree.BuildItems<DisplayBindingDescriptor>(displayBindingPath, null, true); |
|
displayBindingServiceProperties = PropertyService.Get("DisplayBindingService", new Properties()); |
|
foreach (ExternalProcessDisplayBinding binding in displayBindingServiceProperties.Get("ExternalProcesses", new ExternalProcessDisplayBinding[0])) { |
|
if (binding != null) { |
|
AddExternalProcessDisplayBindingInternal(binding); |
|
} |
|
} |
|
} |
|
|
|
public static DisplayBindingDescriptor AddExternalProcessDisplayBinding(ExternalProcessDisplayBinding binding) |
|
{ |
|
WorkbenchSingleton.AssertMainThread(); |
|
if (binding == null) |
|
throw new ArgumentNullException("binding"); |
|
DisplayBindingDescriptor descriptor = AddExternalProcessDisplayBindingInternal(binding); |
|
SaveExternalProcessDisplayBindings(); |
|
return descriptor; |
|
} |
|
|
|
static void SaveExternalProcessDisplayBindings() |
|
{ |
|
displayBindingServiceProperties.Set("ExternalProcesses", externalProcessDisplayBindings.ToArray()); |
|
} |
|
|
|
static DisplayBindingDescriptor AddExternalProcessDisplayBindingInternal(ExternalProcessDisplayBinding binding) |
|
{ |
|
externalProcessDisplayBindings.Add(binding); |
|
DisplayBindingDescriptor descriptor = new DisplayBindingDescriptor(binding) { |
|
Id = binding.Id, |
|
Title = binding.Title |
|
}; |
|
bindings.Add(descriptor); |
|
return descriptor; |
|
} |
|
|
|
public static void RemoveExternalProcessDisplayBinding(ExternalProcessDisplayBinding binding) |
|
{ |
|
WorkbenchSingleton.AssertMainThread(); |
|
if (binding == null) |
|
throw new ArgumentNullException("binding"); |
|
if (!externalProcessDisplayBindings.Remove(binding)) |
|
throw new ArgumentException("binding was not added"); |
|
SaveExternalProcessDisplayBindings(); |
|
for (int i = 0; i < bindings.Count; i++) { |
|
if (bindings[i].GetLoadedBinding() == binding) { |
|
bindings.RemoveAt(i); |
|
return; |
|
} |
|
} |
|
throw new InvalidOperationException("did not find binding descriptor even though binding was registered"); |
|
} |
|
|
|
/// <summary> |
|
/// Gets the primary display binding for the specified file name. |
|
/// </summary> |
|
public static IDisplayBinding GetBindingPerFileName(string filename) |
|
{ |
|
WorkbenchSingleton.AssertMainThread(); |
|
if (FileUtility.IsUrl(filename)) { |
|
// The normal display binding dispatching code can't handle URLs (e.g. because it uses Path.GetExtension), |
|
// so we'll directly return the browser display binding. |
|
return new BrowserDisplayBinding.BrowserDisplayBinding(); |
|
} |
|
DisplayBindingDescriptor codon = GetDefaultCodonPerFileName(filename); |
|
return codon == null ? null : codon.Binding; |
|
} |
|
|
|
/// <summary> |
|
/// Gets the default primary display binding for the specified file name. |
|
/// </summary> |
|
public static DisplayBindingDescriptor GetDefaultCodonPerFileName(string filename) |
|
{ |
|
WorkbenchSingleton.AssertMainThread(); |
|
|
|
string defaultCommandID = displayBindingServiceProperties.Get("Default" + Path.GetExtension(filename).ToLowerInvariant()) as string; |
|
if (!string.IsNullOrEmpty(defaultCommandID)) { |
|
foreach (DisplayBindingDescriptor binding in bindings) { |
|
if (binding.Id == defaultCommandID) { |
|
if (IsPrimaryBindingValidForFileName(binding, filename)) { |
|
return binding; |
|
} |
|
} |
|
} |
|
} |
|
|
|
foreach (DisplayBindingDescriptor binding in bindings) { |
|
if (IsPrimaryBindingValidForFileName(binding, filename) && binding.Binding.IsPreferredBindingForFile(filename)) { |
|
return binding; |
|
} |
|
} |
|
|
|
// var autoDetect = new AutoDetectDisplayBinding(); |
|
// if (autoDetect.AutoDetectFileContent(filename, new MemoryStream(File.ReadAllBytes(filename))) > double.NegativeInfinity) |
|
// return autoDetect.BestDescriptor; |
|
|
|
return null; |
|
} |
|
|
|
public static void SetDefaultCodon(string extension, DisplayBindingDescriptor bindingDescriptor) |
|
{ |
|
WorkbenchSingleton.AssertMainThread(); |
|
if (bindingDescriptor == null) |
|
throw new ArgumentNullException("bindingDescriptor"); |
|
if (extension == null) |
|
throw new ArgumentNullException("extension"); |
|
if (!extension.StartsWith(".", StringComparison.Ordinal)) |
|
throw new ArgumentException("extension must start with '.'"); |
|
|
|
displayBindingServiceProperties.Set("Default" + extension.ToLowerInvariant(), bindingDescriptor.Id); |
|
} |
|
|
|
/// <summary> |
|
/// Gets list of possible primary display bindings for the specified file name. |
|
/// </summary> |
|
public static IList<DisplayBindingDescriptor> GetCodonsPerFileName(string filename) |
|
{ |
|
WorkbenchSingleton.AssertMainThread(); |
|
|
|
List<DisplayBindingDescriptor> list = new List<DisplayBindingDescriptor>(); |
|
foreach (DisplayBindingDescriptor binding in bindings) { |
|
if (IsPrimaryBindingValidForFileName(binding, filename)) { |
|
list.Add(binding); |
|
} |
|
} |
|
return list; |
|
} |
|
|
|
static bool IsPrimaryBindingValidForFileName(DisplayBindingDescriptor binding, string filename) |
|
{ |
|
if (!binding.IsSecondary && binding.CanOpenFile(filename)) { |
|
if (binding.Binding != null && binding.Binding.CanCreateContentForFile(filename)) { |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
/// <summary> |
|
/// Attach secondary view contents to the view content. |
|
/// </summary> |
|
/// <param name="viewContent">The view content to attach to</param> |
|
/// <param name="isReattaching">This is a reattaching pass</param> |
|
public static void AttachSubWindows(IViewContent viewContent, bool isReattaching) |
|
{ |
|
WorkbenchSingleton.AssertMainThread(); |
|
if (viewContent == null) |
|
throw new ArgumentNullException("viewContent"); |
|
|
|
foreach (DisplayBindingDescriptor binding in bindings) { |
|
if (binding.IsSecondary && binding.CanOpenFile(viewContent.PrimaryFileName)) { |
|
ISecondaryDisplayBinding displayBinding = binding.SecondaryBinding; |
|
if (displayBinding != null |
|
&& (!isReattaching || displayBinding.ReattachWhenParserServiceIsReady) |
|
&& displayBinding.CanAttachTo(viewContent)) |
|
{ |
|
IViewContent[] subViewContents = binding.SecondaryBinding.CreateSecondaryViewContent(viewContent); |
|
if (subViewContents != null) { |
|
Array.ForEach(subViewContents, viewContent.SecondaryViewContents.Add); |
|
} else { |
|
MessageService.ShowError("Can't attach secondary view content. " + binding.SecondaryBinding + " returned null for " + viewContent + ".\n(should never happen)"); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
}
|
|
|