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.
553 lines
18 KiB
553 lines
18 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.ComponentModel.Design; |
|
using System.ComponentModel.Design.Serialization; |
|
using System.Drawing; |
|
using System.Drawing.Design; |
|
using System.Drawing.Imaging; |
|
using System.IO; |
|
using System.Linq; |
|
using System.Reflection; |
|
using System.Runtime.Remoting.Lifetime; |
|
using System.Text; |
|
using System.Windows.Forms; |
|
|
|
using ICSharpCode.FormsDesigner.Gui; |
|
using ICSharpCode.FormsDesigner.Services; |
|
using ICSharpCode.FormsDesigner.UndoRedo; |
|
|
|
namespace ICSharpCode.FormsDesigner |
|
{ |
|
/// <summary> |
|
/// Description of FormsDesignerAppDomainHost. |
|
/// </summary> |
|
public class FormsDesignerAppDomainHost : MarshalByRefObject, IServiceProvider |
|
{ |
|
DesignSurface designSurface; |
|
ServiceContainer container; |
|
DesignerLoader loader; |
|
IFormsDesignerLoggingService logger; |
|
Services.MenuCommandService menuCommandService; |
|
IDesignerGenerator generator; |
|
bool unloading; |
|
FormsDesignerAppDomainCreationProperties properties; |
|
readonly Dictionary<Type, TypeDescriptionProvider> addedTypeDescriptionProviders = new Dictionary<Type, TypeDescriptionProvider>(); |
|
|
|
public string DesignSurfaceName { |
|
get { |
|
return (designSurface == null) ? null : designSurface.ToString(); |
|
} |
|
} |
|
|
|
public bool HasDesignerHost { |
|
get { |
|
return Host != null; |
|
} |
|
} |
|
|
|
public bool IsLoaderLoading { |
|
get { |
|
return this.loader != null && this.loader.Loading; |
|
} |
|
} |
|
|
|
public IDesignerHost Host { |
|
get { |
|
if (designSurface == null) |
|
return null; |
|
return (IDesignerHost)designSurface.GetService(typeof(IDesignerHost)); |
|
} |
|
} |
|
|
|
public ServiceContainer Services { |
|
get { return container; } |
|
} |
|
|
|
static readonly DesignSurfaceManager designSurfaceManager = new DesignSurfaceManager(); |
|
|
|
public static FormsDesignerAppDomainHost CreateFormsDesignerInAppDomain(ref AppDomain appDomain, FormsDesignerAppDomainCreationProperties properties) |
|
{ |
|
if (appDomain == null) { |
|
// Construct and initialize settings for a second AppDomain. |
|
AppDomainSetup formsDesignerAppDomainSetup = new AppDomainSetup(); |
|
formsDesignerAppDomainSetup.ApplicationBase = Path.GetDirectoryName(typeof(FormsDesignerAppDomainHost).Assembly.Location); |
|
formsDesignerAppDomainSetup.DisallowBindingRedirects = false; |
|
formsDesignerAppDomainSetup.DisallowCodeDownload = true; |
|
formsDesignerAppDomainSetup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; |
|
|
|
// Create the second AppDomain. |
|
appDomain = AppDomain.CreateDomain("FormsDesigner AD", null, formsDesignerAppDomainSetup); |
|
} |
|
var host = (FormsDesignerAppDomainHost)appDomain.CreateInstanceAndUnwrap(typeof(FormsDesignerAppDomainHost).Assembly.FullName, typeof(FormsDesignerAppDomainHost).FullName); |
|
host.Initialize(properties); |
|
return host; |
|
} |
|
|
|
void Initialize(FormsDesignerAppDomainCreationProperties properties) |
|
{ |
|
this.properties = properties; |
|
this.container = new DefaultServiceContainer(); |
|
container.AddService(typeof(FormsDesignerAppDomainHost), this); |
|
container.AddService(typeof(IFormsDesignerLoggingService), logger = new FormsDesignerLoggingServiceProxy(properties.Logger)); |
|
container.AddService(typeof(System.Drawing.Design.IPropertyValueUIService), new PropertyValueUIService()); |
|
container.AddService(typeof(ITypeResolutionService), new TypeResolutionService(properties.FileName, container, properties.TypeLocator)); |
|
container.AddService(typeof(ITypeDiscoveryService), new TypeDiscoveryService(properties.GacWrapper, container)); |
|
container.AddService(typeof(MemberRelationshipService), new DefaultMemberRelationshipService(container)); |
|
container.AddService(typeof(AmbientProperties), new AmbientProperties()); |
|
container.AddService(typeof(DesignerOptionService), new SharpDevelopDesignerOptionService(properties.Options)); |
|
|
|
this.designSurface = designSurfaceManager.CreateDesignSurface(container); |
|
|
|
var eventBindingService = new Services.EventBindingService(properties.FormsDesignerProxy, designSurface); |
|
this.menuCommandService = new ICSharpCode.FormsDesigner.Services.MenuCommandService(properties.Commands, designSurface); |
|
|
|
container.AddService(typeof(System.ComponentModel.Design.IEventBindingService), eventBindingService); |
|
container.AddService(typeof(System.ComponentModel.Design.IMenuCommandService), menuCommandService.Proxy); |
|
container.AddService(typeof(IToolboxService), new SharpDevelopToolboxService(this)); |
|
container.AddService(typeof(System.ComponentModel.Design.IResourceService), new DesignerResourceService(properties.ResourceStore, this)); |
|
|
|
// Provide the ImageResourceEditor for all Image and Icon properties |
|
addedTypeDescriptionProviders.Add(typeof(Image), TypeDescriptor.AddAttributes(typeof(Image), new EditorAttribute(typeof(ImageResourceEditor), typeof(System.Drawing.Design.UITypeEditor)))); |
|
addedTypeDescriptionProviders.Add(typeof(Icon), TypeDescriptor.AddAttributes(typeof(Icon), new EditorAttribute(typeof(ImageResourceEditor), typeof(System.Drawing.Design.UITypeEditor)))); |
|
|
|
InitializeEvents(); |
|
} |
|
|
|
#region Events |
|
public event EventHandler DesignSurfaceLoading; |
|
|
|
protected virtual void OnDesignSurfaceLoading(EventArgs e) |
|
{ |
|
if (DesignSurfaceLoading != null) { |
|
DesignSurfaceLoading(this, e); |
|
} |
|
} |
|
|
|
public event EventHandler<LoadedEventArgsProxy> DesignSurfaceLoaded; |
|
|
|
protected virtual void OnDesignSurfaceLoaded(LoadedEventArgs e) |
|
{ |
|
if (DesignSurfaceLoaded != null) { |
|
DesignSurfaceLoaded(this, new LoadedEventArgsProxy { HasSucceeded = e.HasSucceeded }); |
|
} |
|
} |
|
|
|
|
|
public event EventHandler DesignSurfaceFlushed; |
|
|
|
protected virtual void OnDesignSurfaceFlushed(EventArgs e) |
|
{ |
|
if (DesignSurfaceFlushed != null) { |
|
DesignSurfaceFlushed(this, e); |
|
} |
|
} |
|
|
|
public event EventHandler DesignSurfaceUnloading; |
|
|
|
protected virtual void OnDesignSurfaceUnloading(EventArgs e) |
|
{ |
|
if (DesignSurfaceUnloading != null) { |
|
DesignSurfaceUnloading(this, e); |
|
} |
|
} |
|
|
|
public event EventHandler DesignSurfaceUnloaded; |
|
|
|
protected virtual void OnDesignSurfaceUnloaded(EventArgs e) |
|
{ |
|
if (DesignSurfaceUnloaded != null) { |
|
DesignSurfaceUnloaded(this, e); |
|
} |
|
} |
|
|
|
public event EventHandler<ComponentEventArgsProxy> ComponentAdded; |
|
|
|
protected virtual void OnComponentAdded(ComponentEventArgsProxy e) |
|
{ |
|
if (ComponentAdded != null) { |
|
ComponentAdded(this, e); |
|
} |
|
} |
|
|
|
public event EventHandler<ComponentEventArgsProxy> ComponentRemoved; |
|
|
|
protected virtual void OnComponentRemoved(ComponentEventArgsProxy e) |
|
{ |
|
if (ComponentRemoved != null) { |
|
ComponentRemoved(this, e); |
|
} |
|
} |
|
|
|
public event EventHandler<ComponentRenameEventArgsProxy> ComponentRename; |
|
|
|
protected virtual void OnComponentRename(ComponentRenameEventArgsProxy e) |
|
{ |
|
if (ComponentRename != null) { |
|
ComponentRename(this, e); |
|
} |
|
} |
|
|
|
public event DesignerTransactionCloseEventHandler HostTransactionClosed; |
|
|
|
protected virtual void OnHostTransactionClosed(DesignerTransactionCloseEventArgs e) |
|
{ |
|
if (HostTransactionClosed != null) { |
|
HostTransactionClosed(this, e); |
|
} |
|
} |
|
|
|
void ComponentChanged(object sender, ComponentChangedEventArgs e) |
|
{ |
|
bool loading = IsLoaderLoading; |
|
LoggingService.Debug("Forms designer: ComponentChanged: " + (e.Component == null ? "<null>" : e.Component.ToString()) + ", Member=" + (e.Member == null ? "<null>" : e.Member.Name) + ", OldValue=" + (e.OldValue == null ? "<null>" : e.OldValue.ToString()) + ", NewValue=" + (e.NewValue == null ? "<null>" : e.NewValue.ToString()) + "; Loading=" + loading + "; Unloading=" + this.unloading); |
|
if (!loading && !unloading) { |
|
try { |
|
properties.FormsDesignerProxy.MakeDirty(); |
|
if (e.Component != null && e.Member != null && e.Member.Name == "Name" && |
|
e.NewValue is string && !object.Equals(e.OldValue, e.NewValue)) { |
|
// changing the name of the component |
|
generator.NotifyComponentRenamed(e.Component, (string)e.NewValue, (string)e.OldValue); |
|
} |
|
} catch (Exception ex) { |
|
MessageService.ShowException(ex, ""); |
|
} |
|
} |
|
} |
|
|
|
bool shouldUpdateSelectableObjects = false; |
|
|
|
void TransactionClose(object sender, DesignerTransactionCloseEventArgs e) |
|
{ |
|
if (shouldUpdateSelectableObjects) { |
|
// update the property pad after the transaction is *really* finished |
|
// (including updating the selection) |
|
DesignSurfaceView.BeginInvoke((Action)UpdatePropertyPad); |
|
shouldUpdateSelectableObjects = false; |
|
} |
|
} |
|
|
|
void ComponentListChanged(object sender, EventArgs e) |
|
{ |
|
LoggingService.Debug("Forms designer: Component added/removed/renamed, Loading=" + IsLoaderLoading + ", Unloading=" + this.unloading); |
|
if (!IsLoaderLoading && !unloading) { |
|
shouldUpdateSelectableObjects = true; |
|
properties.FormsDesignerProxy.MakeDirty(); |
|
} |
|
} |
|
|
|
void InitializeEvents() |
|
{ |
|
designSurface.Loading += designSurface_Loading; |
|
designSurface.Loaded += designSurface_Loaded; |
|
designSurface.Flushed += designSurface_Flushed; |
|
designSurface.Unloading += designSurface_Unloading; |
|
designSurface.Unloaded += designSurface_Unloading; |
|
|
|
IComponentChangeService componentChangeService = (IComponentChangeService)GetService(typeof(IComponentChangeService)); |
|
if (componentChangeService != null) { |
|
componentChangeService.ComponentChanged += ComponentChanged; |
|
componentChangeService.ComponentAdded += ComponentListChanged; |
|
componentChangeService.ComponentRemoved += ComponentListChanged; |
|
componentChangeService.ComponentRename += ComponentListChanged; |
|
} |
|
|
|
ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService; |
|
if (selectionService != null) { |
|
selectionService.SelectionChanged += SelectionServiceSelectionChanged; |
|
} |
|
|
|
Host.TransactionClosed += TransactionClose; |
|
} |
|
|
|
void SelectionServiceSelectionChanged(object sender, EventArgs e) |
|
{ |
|
UpdatePropertyPadSelection((ISelectionService)sender); |
|
} |
|
|
|
void Host_TransactionClosed(object sender, DesignerTransactionCloseEventArgs e) |
|
{ |
|
OnHostTransactionClosed(e); |
|
} |
|
|
|
void componentChangeService_ComponentRename(object sender, ComponentRenameEventArgs e) |
|
{ |
|
OnComponentRename(new ComponentRenameEventArgsProxy { Component = e.Component, NewName = e.NewName, OldName = e.OldName }); |
|
} |
|
|
|
void componentChangeService_ComponentRemoved(object sender, ComponentEventArgs e) |
|
{ |
|
OnComponentRemoved(new ComponentEventArgsProxy { Component = e.Component }); |
|
} |
|
|
|
void componentChangeService_ComponentAdded(object sender, ComponentEventArgs e) |
|
{ |
|
OnComponentAdded(new ComponentEventArgsProxy { Component = e.Component }); |
|
} |
|
|
|
void designSurface_Unloaded(object sender, EventArgs e) |
|
{ |
|
OnDesignSurfaceUnloaded(e); |
|
} |
|
|
|
void designSurface_Unloading(object sender, EventArgs e) |
|
{ |
|
unloading = true; |
|
OnDesignSurfaceUnloading(e); |
|
} |
|
|
|
void designSurface_Flushed(object sender, EventArgs e) |
|
{ |
|
OnDesignSurfaceFlushed(e); |
|
} |
|
|
|
void designSurface_Loaded(object sender, LoadedEventArgs e) |
|
{ |
|
unloading = false; |
|
OnDesignSurfaceLoaded(e); |
|
} |
|
|
|
void designSurface_Loading(object sender, EventArgs e) |
|
{ |
|
unloading = false; |
|
OnDesignSurfaceLoading(e); |
|
} |
|
#endregion |
|
|
|
public void ActivateDesignSurface() |
|
{ |
|
designSurfaceManager.ActiveDesignSurface = this.designSurface; |
|
} |
|
|
|
public static void DeactivateDesignSurface() |
|
{ |
|
designSurfaceManager.ActiveDesignSurface = null; |
|
} |
|
|
|
public bool IsActiveDesignSurface { |
|
get { return designSurfaceManager.ActiveDesignSurface == this.designSurface; } |
|
} |
|
|
|
public object GetService(Type serviceType) |
|
{ |
|
var svc = designSurface.GetService(serviceType); |
|
return svc; |
|
} |
|
|
|
public void BeginDesignSurfaceLoad(IDesignerGenerator generator, IDesignerLoaderProvider loaderProvider) |
|
{ |
|
var loader = new SharpDevelopDesignerLoader(this, generator, loaderProvider.CreateLoader(generator)); |
|
var provider = loader.GetCodeDomProviderInstance(); |
|
this.generator = generator; |
|
if (provider != null) { |
|
AddService(typeof(System.CodeDom.Compiler.CodeDomProvider), provider); |
|
} |
|
this.loader = loader; |
|
|
|
designSurface.BeginLoad(loader); |
|
} |
|
|
|
static string FormatLoadErrors(DesignSurface designSurface) |
|
{ |
|
StringBuilder sb = new StringBuilder(); |
|
foreach(Exception le in designSurface.LoadErrors) { |
|
sb.AppendLine(le.ToString()); |
|
sb.AppendLine(); |
|
} |
|
return sb.ToString(); |
|
} |
|
|
|
public string LoadErrors { |
|
get { return FormatLoadErrors(designSurface); } |
|
} |
|
|
|
public bool IsDesignSurfaceLoaded { |
|
get { return designSurface.IsLoaded; } |
|
} |
|
|
|
public bool ReferencedAssemblyChanged { |
|
get { |
|
var typeResolutionService = (TypeResolutionService)GetService(typeof(ITypeResolutionService)); |
|
return typeResolutionService != null && typeResolutionService.ReferencedAssemblyChanged; |
|
} |
|
} |
|
|
|
public void FlushDesignSurface() |
|
{ |
|
designSurface.Flush(); |
|
} |
|
|
|
bool isDesignSurfaceViewInitialized = false; |
|
|
|
public Control DesignSurfaceView { |
|
get { |
|
var designView = (Control)designSurface.View; |
|
if (!isDesignSurfaceViewInitialized) { |
|
designView.BackColor = Color.White; |
|
designView.RightToLeft = RightToLeft.No; |
|
isDesignSurfaceViewInitialized = true; |
|
} |
|
return designView; |
|
} |
|
} |
|
|
|
public void DisposeDesignSurface() |
|
{ |
|
designSurface.Dispose(); |
|
} |
|
|
|
PropertyPadContent propertyPad; |
|
|
|
public PropertyPadContent CreatePropertyPad() |
|
{ |
|
if (propertyPad == null) |
|
propertyPad = new PropertyPadContent(Host, properties.FormsDesignerProxy); |
|
return propertyPad; |
|
} |
|
|
|
public void UpdatePropertyPad() |
|
{ |
|
if (HasDesignerHost) { |
|
propertyPad.SelectableObjects = Host.Container.Components; |
|
ISelectionService selectionService = (ISelectionService)GetService(typeof(ISelectionService)); |
|
if (selectionService != null) { |
|
UpdatePropertyPadSelection(selectionService); |
|
} |
|
} |
|
} |
|
|
|
public void UpdatePropertyPadSelection(ISelectionService selectionService) |
|
{ |
|
var selection = selectionService.GetSelectedComponents(); |
|
object[] selArray = new object[selection.Count]; |
|
selection.CopyTo(selArray, 0); |
|
propertyPad.SelectedObjects = selArray; |
|
properties.FormsDesignerProxy.InvalidateRequerySuggested(); |
|
} |
|
|
|
public IFormsDesignerLoggingService LoggingService { |
|
get { |
|
return GetService(typeof(IFormsDesignerLoggingService)) as IFormsDesignerLoggingService; |
|
} |
|
} |
|
|
|
public IMenuCommandService MenuCommandService { |
|
get { |
|
return menuCommandService.Proxy; |
|
} |
|
} |
|
|
|
public ISelectionService SelectionService { |
|
get { |
|
return new SelectionServiceProxy(GetService(typeof(ISelectionService)) as ISelectionService); |
|
} |
|
} |
|
|
|
List<IDesignerVerbProxy> designerVerbs; |
|
|
|
public List<IDesignerVerbProxy> CommandVerbs { |
|
get { |
|
if (designerVerbs == null) { |
|
designerVerbs = new List<IDesignerVerbProxy>(); |
|
designerVerbs.AddRange(((IMenuCommandService)GetService(typeof(IMenuCommandService))).Verbs.OfType<DesignerVerb>().Select(dv => new DesignerVerbProxy(dv))); |
|
} |
|
|
|
return designerVerbs; |
|
} |
|
} |
|
|
|
public IMessageService MessageService { |
|
get { |
|
return GetService(typeof(IMessageService)) as IMessageService; |
|
} |
|
} |
|
|
|
public void AddService(Type type, object service) |
|
{ |
|
Services.AddService(type, service); |
|
} |
|
|
|
public Stream LoadComponentIconStream(ToolComponent component) |
|
{ |
|
Assembly asm = component.LoadAssembly(); |
|
Type type = asm.GetType(component.FullName); |
|
Stream s = null; |
|
if (type != null) { |
|
object[] attributes = type.GetCustomAttributes(false); |
|
foreach (object attr in attributes) { |
|
if (attr is ToolboxBitmapAttribute) { |
|
ToolboxBitmapAttribute toolboxBitmapAttribute = (ToolboxBitmapAttribute)attr; |
|
var img = new Bitmap(toolboxBitmapAttribute.GetImage(type)); |
|
s = new MemoryStream(); |
|
img.Save(s, ImageFormat.Png); |
|
break; |
|
} |
|
} |
|
} |
|
if (s == null) { |
|
try { |
|
Stream imageStream = asm.GetManifestResourceStream(component.FullName + ".bmp"); |
|
if (imageStream != null) { |
|
var img = new Bitmap(Image.FromStream(imageStream)); |
|
s = new MemoryStream(); |
|
img.Save(s, ImageFormat.Png); |
|
} |
|
} catch (Exception e) { |
|
logger.Warn("ComponentLibraryLoader.GetIcon: " + e.Message); |
|
} |
|
} |
|
|
|
// TODO: Maybe default icon needed ??!?! |
|
return s; |
|
} |
|
|
|
public AssemblyName GetAssemblyName(ToolComponent component) |
|
{ |
|
return component.LoadAssembly().GetName(); |
|
} |
|
|
|
public void InitializeRemainingServices() |
|
{ |
|
var undoEngine = new FormsDesignerUndoEngine(this); |
|
container.AddService(typeof(UndoEngine), undoEngine); |
|
container.AddService(typeof(IFormsDesignerUndoEngine), new FormsDesignerUndoEngineProxy(undoEngine)); |
|
} |
|
|
|
public void UseSDAssembly(string name, string location) |
|
{ |
|
AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs args) { |
|
LoggingService.DebugFormatted("Looking for: {0} in {1} {2}", args.Name, name, location); |
|
if (args.Name == name) |
|
return Assembly.LoadFile(location); |
|
return null; |
|
}; |
|
} |
|
|
|
public void RaiseApplicationIdle() |
|
{ |
|
Application.RaiseIdle(EventArgs.Empty); |
|
} |
|
|
|
public void UnregisterTypeProviders() |
|
{ |
|
foreach (KeyValuePair<Type, TypeDescriptionProvider> entry in addedTypeDescriptionProviders) { |
|
TypeDescriptor.RemoveProvider(entry.Value, entry.Key); |
|
} |
|
addedTypeDescriptionProviders.Clear(); |
|
} |
|
} |
|
|
|
public class FormsDesignerAppDomainCreationProperties : MarshalByRefObject |
|
{ |
|
public string FileName { get; set; } |
|
public ITypeLocator TypeLocator { get; set; } |
|
public IGacWrapper GacWrapper { get; set; } |
|
public ICommandProvider Commands { get; set; } |
|
public IFormsDesigner FormsDesignerProxy { get; set; } |
|
public IFormsDesignerLoggingService Logger { get; set; } |
|
public SharpDevelopDesignerOptions Options { get; set; } |
|
public IResourceStore ResourceStore { get; set; } |
|
} |
|
}
|
|
|