#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.
 
 
 
 
 
 

175 lines
7.2 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.CodeDom.Compiler;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Reflection;
using System.Text;
using ICSharpCode.Core;
using ICSharpCode.FormsDesigner.Services;
namespace ICSharpCode.FormsDesigner
{
/// <summary>
/// An abstract base class for CodeDOM designer loaders.
/// </summary>
public abstract class AbstractCodeDomDesignerLoader : CodeDomDesignerLoader
{
bool loading;
IDesignerLoaderHost designerLoaderHost = null;
ITypeResolutionService typeResolutionService = null;
readonly IDesignerGenerator generator;
public override bool Loading {
get { return base.Loading || loading; }
}
protected override ITypeResolutionService TypeResolutionService {
get { return this.typeResolutionService; }
}
protected IDesignerLoaderHost DesignerLoaderHost {
get { return this.designerLoaderHost; }
}
protected override CodeDomProvider CodeDomProvider {
get { return this.generator.CodeDomProvider; }
}
protected IDesignerGenerator Generator {
get { return this.generator; }
}
protected AbstractCodeDomDesignerLoader(IDesignerGenerator generator)
{
if (generator == null) {
throw new ArgumentNullException("generator", "Generator cannot be null");
}
this.generator = generator;
}
public override void Dispose()
{
try {
IComponentChangeService componentChangeService = (IComponentChangeService)this.GetService(typeof(IComponentChangeService));
if (componentChangeService != null) {
LoggingService.Debug("Forms designer: Removing ComponentAdded handler for nested container setup");
componentChangeService.ComponentAdded -= ComponentContainerSetUp;
} else {
LoggingService.Info("Forms designer: Could not remove ComponentAdding handler because IComponentChangeService is no longer available");
}
} finally {
base.Dispose();
}
}
public override void BeginLoad(IDesignerLoaderHost host)
{
this.loading = true;
this.typeResolutionService = (ITypeResolutionService)host.GetService(typeof(ITypeResolutionService));
this.designerLoaderHost = host;
base.BeginLoad(host);
}
static void ComponentContainerSetUp(object sender, ComponentEventArgs e)
{
// HACK: This reflection mess fixes SD2-1374 and SD2-1375. However I am not sure why it is needed in the first place.
// There seems to be a problem with the nested container class used
// by the designer. It only establishes a connection to the service
// provider of the DesignerHost after it has been queried for
// an IServiceContainer service. This does not always happen
// automatically, so we enforce that here. We have to use
// reflection because the request for IServiceContainer is
// not forwarded by higher-level GetService methods.
// Also, be very careful when trying to troubleshoot this using
// the debugger because it automatically gets all properties and
// this can cause side effects here, such as initializing that service
// so that the problem no longer appears.
INestedContainer nestedContainer = e.Component.Site.GetService(typeof(INestedContainer)) as INestedContainer;
if (nestedContainer != null) {
MethodInfo getServiceMethod = nestedContainer.GetType().GetMethod("GetService", BindingFlags.Instance | BindingFlags.NonPublic, null, new [] {typeof(Type)}, null);
if (getServiceMethod != null) {
LoggingService.Debug("Forms designer: Initializing nested service container of " + e.Component.ToString() + " using Reflection");
getServiceMethod.Invoke(nestedContainer, BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic, null, new [] {typeof(IServiceContainer)}, null);
}
}
}
protected override void Initialize()
{
CodeDomLocalizationModel model = FormsDesigner.Gui.OptionPanels.LocalizationModelOptionsPanel.DefaultLocalizationModel;
if (FormsDesigner.Gui.OptionPanels.LocalizationModelOptionsPanel.KeepLocalizationModel) {
// Try to find out the current localization model of the designed form
CodeDomLocalizationModel existingModel = this.GetCurrentLocalizationModelFromDesignedFile();
if (existingModel != CodeDomLocalizationModel.None) {
LoggingService.Debug("Determined existing localization model, using that: " + existingModel.ToString());
model = existingModel;
} else {
LoggingService.Debug("Could not determine existing localization model, using default: " + model.ToString());
}
} else {
LoggingService.Debug("Using default localization model: " + model.ToString());
}
CodeDomLocalizationProvider localizationProvider = new CodeDomLocalizationProvider(designerLoaderHost, model);
IDesignerSerializationManager manager = (IDesignerSerializationManager)designerLoaderHost.GetService(typeof(IDesignerSerializationManager));
manager.AddSerializationProvider(new SharpDevelopSerializationProvider());
manager.AddSerializationProvider(localizationProvider);
base.Initialize();
IComponentChangeService componentChangeService = (IComponentChangeService)this.GetService(typeof(IComponentChangeService));
if (componentChangeService != null) {
LoggingService.Debug("Forms designer: Adding ComponentAdded handler for nested container setup");
componentChangeService.ComponentAdded += ComponentContainerSetUp;
} else {
LoggingService.Warn("Forms designer: Cannot add ComponentAdded handler for nested container setup because IComponentChangeService is unavailable");
}
}
/// <summary>
/// When overridden in derived classes, this method should return the current
/// localization model of the designed file or None, if it cannot be determined.
/// </summary>
/// <returns>The default implementation always returns None.</returns>
protected virtual CodeDomLocalizationModel GetCurrentLocalizationModelFromDesignedFile()
{
return CodeDomLocalizationModel.None;
}
protected override void OnEndLoad(bool successful, ICollection errors)
{
this.loading = false;
//when control's Dispose() has a exception and on loading also raised exception
//then this is only place where this error can be logged, because after errors is
//catched internally in .net
try {
base.OnEndLoad(successful, errors);
} catch(ExceptionCollection e) {
LoggingService.Error("DesignerLoader.OnEndLoad error " + e.Message, e);
foreach(Exception ine in e.Exceptions) {
LoggingService.Error("DesignerLoader.OnEndLoad error " + ine.Message, ine);
}
throw;
} catch(Exception e) {
LoggingService.Error("DesignerLoader.OnEndLoad error " + e.Message, e);
throw;
}
}
protected override void ReportFlushErrors(ICollection errors)
{
StringBuilder sb = new StringBuilder(StringParser.Parse("${res:ICSharpCode.SharpDevelop.FormDesigner.ReportFlushErrors}") + Environment.NewLine + Environment.NewLine);
foreach (var error in errors) {
sb.AppendLine(error.ToString());
sb.AppendLine();
}
MessageService.ShowError(sb.ToString());
}
}
}